王新阳

wangxinyang

未解之谜

百度搜索算法规范详解https://zy.baidu.com/act/guide?isResponsible=1

百度搜索优化知识大全https://zy.baidu.com/act/seo?isResponsible=1

阿里云开发者课堂 https://edu.aliyun.com/

spark-md5.js 计算文件md5值 :https://github.com/satazor/js-spark-md5

一个提供用户脚本的网站
https://greasyfork.org/zh-CN

用户脚本管理器:Tampermonkey中文文档
https://www.cnblogs.com/grubber/p/12560522.html

Js上传插件 Plupload

drupal

嵌入式WEB开发

CSRF 漏洞

fopen漏洞

Python
阿里云大学PYTHON学习路线
https://edu.aliyun.com/roadmap/python

ThinkPHP list_to_tree、tree_to_list、list_search

vue.js

C盘可以删除的临时文件,也可以用系统自带的磁盘清理程序清除
C:\Windows\ServiceProfiles\NetworkService\AppData\Local\Temp
C:\Windows\SoftwareDistribution\Download
https://support.microsoft.com/zh-cn/windows?ui=zh-CN&rs=zh-CN&ad=CN
https://support.microsoft.com/zh-cn/windows/%E9%87%8A%E6%94%BE-windows-10-%E4%B8%AD%E7%9A%84%E9%A9%B1%E5%8A%A8%E5%99%A8%E7%A9%BA%E9%97%B4-85529ccb-c365-490d-b548-831022bc9b32

windows指定图片使用照片查看器打开

常见图片格式在右键》属性》打开方式中即可设置。

如果打开方式中没有"照片查看器",可以在注册表如下路径:

计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Photo Viewer\Capabilities\FileAssociations

新建字符串值,名称如:.webp,数值:PhotoViewer.FileAssoc.Tiff

注意:用Windows照片查看器浏览 webp格式 的图片可能会出现较大色差。

使用ffmpeg下载合并ts视频为mp4

1、下载ffmpeg

https://www.gyan.dev/ffmpeg/builds/

2、解压后,window dos 进入相应的bin目录

3、运行ffmpeg合并ts文件

ffmpeg -i "d:\下载.m3u8" -c copy "d:\合并.mp4"

出现下面错误时,可加相应参数解决:
Filename extension of 'd:\下载\crypt.key' is not a common multimedia extension, blocked for security reasons.If you wish to override this adjust allowed_extensions, you can set it to 'ALL' to allow all

ffmpeg -allowed_extensions ALL -i "d:\下载.m3u8" -c copy "d:\合并.mp4"

------------------------

关于 IV(初始化向量):

检查您的 M3U8 文件,#EXT-X-KEY 标签中是否包含了 IV 参数(例如 IV=0x1234567890ABCDEF1234567890ABCDEF)。

如果没有指定 IV,FFmpeg 可能会使用默认值(比如序列号或全零)。如果解密后视频花屏或无法播放,可以尝试在 FFmpeg 命令中手动指定 IV(如果已知):

ffmpeg -allowed_extensions ALL -decryption_iv 1234567890ABCDEF1234567890ABCDEF -i "input.m3u8" -c copy "output.ts"

密钥格式:FFmpeg 期望的密钥通常是二进制文件或十六进制字符串。如果您的密钥是 Base64 编码的,需要先解码。可以使用在线 Base64 解码工具,或者使用 Python/Node.js 等脚本语言进行转换

CSS改变png图标颜色

主要用途:改变纯色线描icon小图标颜色

<div class="masked-line"></div>
 
<style>
  .masked-line {
    width: 200px;
    height: 200px;
    background-color: purple; /* 目标颜色 */
    -webkit-mask-image: url('your-image.png');
    mask-image: url('your-image.png');
  }
</style>

原图:

变红

html根据坐标生成百度地图、高德地图导航地址

百度地图

https://map.baidu.com/?latlng=36.683544,117.032171&title=济南市大明湖公园&content=山东省济南市历下区大明湖路271号&autoOpen=true&l=

高德地图

http://ditu.amap.com/regeo?lng=104.06074583530426&lat=30.5379691198173

分别用js、php实现GS84与GCJ02两种坐标系的互转

高德地图: 使用 GCJ-02 坐标系,也称为火星坐标系。它是基于国际标准 WGS-84 坐标系进行加密处理得到的。
百度地图: 采用 BD-09 坐标系,这是在 GCJ-02 基础上进行二次加密而来的,具有更高的安全性和隐私保护。
天地图: 使用 CGCS2000 坐标系,该坐标系与 WGS-84 存在微小偏差,在要求不高的情况下可以直接与 WGS-84 互换使用。

js

/**
 * WGS84转GCJ02(火星坐标系)
 * @param {number} wgsLon WGS84坐标系的经度
 * @param {number} wgsLat WGS84坐标系的纬度
 * @returns {Array} GCJ02坐标 [经度, 纬度]
 */
function wgs84ToGcj02(wgsLon, wgsLat) {
    const PI = 3.14159265358979324;
    const a = 6378245.0;
    const ee = 0.00669342162296594323;
    
    if (outOfChina(wgsLat, wgsLon)) {
        return [wgsLon, wgsLat];
    }
    
    let dLat = transformLat(wgsLon - 105.0, wgsLat - 35.0);
    let dLon = transformLon(wgsLon - 105.0, wgsLat - 35.0);
    
    const radLat = wgsLat / 180.0 * PI;
    let magic = Math.sin(radLat);
    magic = 1 - ee * magic * magic;
    const sqrtMagic = Math.sqrt(magic);
    
    dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI);
    dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * PI);
    
    const gcjLat = wgsLat + dLat;
    const gcjLon = wgsLon + dLon;
    
    return [gcjLon, gcjLat];
}

/**
 * GCJ02(火星坐标系)转WGS84
 * @param {number} gcjLon GCJ02坐标系的经度
 * @param {number} gcjLat GCJ02坐标系的纬度
 * @returns {Array} WGS84坐标 [经度, 纬度]
 */
function gcj02ToWgs84(gcjLon, gcjLat) {
    const PI = 3.14159265358979324;
    const a = 6378245.0;
    const ee = 0.00669342162296594323;
    
    if (outOfChina(gcjLat, gcjLon)) {
        return [gcjLon, gcjLat];
    }
    
    let dLat = transformLat(gcjLon - 105.0, gcjLat - 35.0);
    let dLon = transformLon(gcjLon - 105.0, gcjLat - 35.0);
    
    const radLat = gcjLat / 180.0 * PI;
    let magic = Math.sin(radLat);
    magic = 1 - ee * magic * magic;
    const sqrtMagic = Math.sqrt(magic);
    
    dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI);
    dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * PI);
    
    const wgsLat = gcjLat - dLat;
    const wgsLon = gcjLon - dLon;
    
    return [wgsLon, wgsLat];
}

function transformLat(x, y) {
    let ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
    ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0;
    ret += (20.0 * Math.sin(y * Math.PI) + 40.0 * Math.sin(y / 3.0 * Math.PI)) * 2.0 / 3.0;
    ret += (160.0 * Math.sin(y / 12.0 * Math.PI) + 320 * Math.sin(y * Math.PI / 30.0)) * 2.0 / 3.0;
    return ret;
}

function transformLon(x, y) {
    let ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
    ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0;
    ret += (20.0 * Math.sin(x * Math.PI) + 40.0 * Math.sin(x / 3.0 * Math.PI)) * 2.0 / 3.0;
    ret += (150.0 * Math.sin(x / 12.0 * Math.PI) + 300.0 * Math.sin(x / 30.0 * Math.PI)) * 2.0 / 3.0;
    return ret;
}

function outOfChina(lat, lon) {
    return lon < 72.004 || lon > 137.8347 || lat < 0.8293 || lat > 55.8271;
}

// 使用示例
// let gcjCoord = wgs84ToGcj02(116.404, 39.915); // WGS84转GCJ02
// let wgsCoord = gcj02ToWgs84(116.404, 39.915); // GCJ02转WGS84

PHP

/**
 * WGS84转GCJ02(火星坐标系)
 * @param float $wgsLon WGS84坐标系的经度
 * @param float $wgsLat WGS84坐标系的纬度
 * @return array GCJ02坐标 [经度, 纬度]
 */
function wgs84ToGcj02($wgsLon, $wgsLat) {
    $PI = 3.14159265358979324;
    $a = 6378245.0;
    $ee = 0.00669342162296594323;
    
    if (outOfChina($wgsLat, $wgsLon)) {
        return array($wgsLon, $wgsLat);
    }
    
    $dLat = transformLat($wgsLon - 105.0, $wgsLat - 35.0);
    $dLon = transformLon($wgsLon - 105.0, $wgsLat - 35.0);
    
    $radLat = $wgsLat / 180.0 * $PI;
    $magic = sin($radLat);
    $magic = 1 - $ee * $magic * $magic;
    $sqrtMagic = sqrt($magic);
    
    $dLat = ($dLat * 180.0) / (($a * (1 - $ee)) / ($magic * $sqrtMagic) * $PI);
    $dLon = ($dLon * 180.0) / ($a / $sqrtMagic * cos($radLat) * $PI);
    
    $gcjLat = $wgsLat + $dLat;
    $gcjLon = $wgsLon + $dLon;
    
    return array($gcjLon, $gcjLat);
}

/**
 * GCJ02(火星坐标系)转WGS84
 * @param float $gcjLon GCJ02坐标系的经度
 * @param float $gcjLat GCJ02坐标系的纬度
 * @return array WGS84坐标 [经度, 纬度]
 */
function gcj02ToWgs84($gcjLon, $gcjLat) {
    $PI = 3.14159265358979324;
    $a = 6378245.0;
    $ee = 0.00669342162296594323;
    
    if (outOfChina($gcjLat, $gcjLon)) {
        return array($gcjLon, $gcjLat);
    }
    
    $dLat = transformLat($gcjLon - 105.0, $gcjLat - 35.0);
    $dLon = transformLon($gcjLon - 105.0, $gcjLat - 35.0);
    
    $radLat = $gcjLat / 180.0 * $PI;
    $magic = sin($radLat);
    $magic = 1 - $ee * $magic * $magic;
    $sqrtMagic = sqrt($magic);
    
    $dLat = ($dLat * 180.0) / (($a * (1 - $ee)) / ($magic * $sqrtMagic) * $PI);
    $dLon = ($dLon * 180.0) / ($a / $sqrtMagic * cos($radLat) * $PI);
    
    $wgsLat = $gcjLat - $dLat;
    $wgsLon = $gcjLon - $dLon;
    
    return array($wgsLon, $wgsLat);
}

function transformLat($x, $y) {
    $ret = -100.0 + 2.0 * $x + 3.0 * $y + 0.2 * $y * $y + 0.1 * $x * $y + 0.2 * sqrt(abs($x));
    $ret += (20.0 * sin(6.0 * $x * M_PI) + 20.0 * sin(2.0 * $x * M_PI)) * 2.0 / 3.0;
    $ret += (20.0 * sin($y * M_PI) + 40.0 * sin($y / 3.0 * M_PI)) * 2.0 / 3.0;
    $ret += (160.0 * sin($y / 12.0 * M_PI) + 320 * sin($y * M_PI / 30.0)) * 2.0 / 3.0;
    return $ret;
}

function transformLon($x, $y) {
    $ret = 300.0 + $x + 2.0 * $y + 0.1 * $x * $x + 0.1 * $x * $y + 0.1 * sqrt(abs($x));
    $ret += (20.0 * sin(6.0 * $x * M_PI) + 20.0 * sin(2.0 * $x * M_PI)) * 2.0 / 3.0;
    $ret += (20.0 * sin($x * M_PI) + 40.0 * sin($x / 3.0 * M_PI)) * 2.0 / 3.0;
    $ret += (150.0 * sin($x / 12.0 * M_PI) + 300.0 * sin($x / 30.0 * M_PI)) * 2.0 / 3.0;
    return $ret;
}

function outOfChina($lat, $lon) {
    return $lon < 72.004 || $lon > 137.8347 || $lat < 0.8293 || $lat > 55.8271;
}

// 使用示例
// $gcjCoord = wgs84ToGcj02(116.404, 39.915); // WGS84转GCJ02
// $wgsCoord = gcj02ToWgs84(116.404, 39.915); // GCJ02转WGS84

layui表单中label宽度自适应

@media(min-width:451px){
	.layui-form-item{display:flex;align-items:center;}
	.layui-form-label{flex:0 0 auto;width:auto !important;min-width:120px;}
	.layui-form-pane .layui-input-block{flex:1;margin-left:-1px;}
}

效果如下图:

PHP 中将字符串转换为字符数组

方法1:使用 str_split() 函数

$string = "Hello";
$array = str_split($string);

print_r($array);
// 输出:Array ( [0] => H [1] => e [2] => l [3] => l [4] => o )

方法2:使用 preg_split() 正则表达式分割

preg_split() 函数配合 UTF-8 模式可以正确处理多字节字符(如中文、日文、表情符号等),将它们分割为单个字符的数组。

$string = "你好,World";
$array = preg_split('//u', $string, -1, PREG_SPLIT_NO_EMPTY);

print_r($array);
// 输出:Array ( [0] => 你 [1] => 好 [2] => , [3] => W [4] => o [5] => r [6] => l [7] => d )

方法3:使用 mb_str_split() 处理多字节字符(PHP 7.4+)

$string = "你好";
$array = mb_str_split($string);

print_r($array);
// 输出:Array ( [0] => 你 [1] => 好 )

preg_split()参数说明:
'//u' - 正则表达式模式,u 修饰符表示 UTF-8 模式
$string - 要分割的字符串
-1 - 表示不限制分割次数
PREG_SPLIT_NO_EMPTY - 过滤掉空元素

js保存剪切板中的截图

来源:deepseek

<!DOCTYPE html>
<html>
<head>
    <title>保存截图工具</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
        }
        .container {
            border: 2px dashed #ccc;
            padding: 20px;
            text-align: center;
            margin-top: 20px;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <h1>截图保存工具</h1>
    <p>1. 使用微信或其他截图工具截取屏幕</p>
    <p>2. 点击下方区域后按Ctrl+V(Windows)或Command+V(Mac)粘贴</p>
    <p>3. 图片将自动下载</p>
    
    <div class="container" id="pasteArea">
        点击此处后粘贴截图
    </div>

    <script>
        const pasteArea = document.getElementById('pasteArea');
        
        pasteArea.addEventListener('click', function() {
            pasteArea.textContent = '请按Ctrl+V/Command+V粘贴截图...';
            // 只添加一次性的监听器
            document.addEventListener('paste', handlePaste, { once: true });
        });

        function handlePaste(event) {
            const items = (event.clipboardData || window.clipboardData).items;
            
            for (let i = 0; i < items.length; i++) {
                if (items[i].type.indexOf('image') !== -1) {
                    const blob = items[i].getAsFile();
                    if (blob) {
                        saveImage(blob);
                        alert('截图已保存!');
                    }
                    event.preventDefault();
                    pasteArea.textContent = '截图已处理,如需再次保存请点击此处';
                    return;
                }
            }
            
            alert('未检测到图片,请确保已复制截图图像');
            pasteArea.textContent = '截图未识别,请点击此处重试';
        }

        function saveImage(blob) {
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            
            const now = new Date();
            const timestamp = `${now.getFullYear()}${(now.getMonth()+1).toString().padStart(2, '0')}${now.getDate().toString().padStart(2, '0')}_${now.getHours().toString().padStart(2, '0')}${now.getMinutes().toString().padStart(2, '0')}${now.getSeconds().toString().padStart(2, '0')}`;
            a.download = `screenshot_${timestamp}.png`;
            
            document.body.appendChild(a);
            a.click();
            
            setTimeout(() => {
                document.body.removeChild(a);
                window.URL.revokeObjectURL(url);
            }, 100);
        }
    </script>
</body>
</html>

PHP按目标比例和尺寸缩小并裁切图片

重点是关于图片翻转、旋转部分的处理

/**
 * 按目标比例和尺寸缩小并裁切图片,如果原图尺寸小于目标尺寸,则只按比例裁切
 * @param $img_name 原图片名称(不是路径)
 * @param $width 目标图片宽度,如果原图宽度不等于目标宽度,则原图按目标比例缩放后再裁切
 * @param $width 目标图片高度
 */
private function img_convert_do($img_name, $width, $height){
	//$new_name=date('YmdHis').my_str_shuffle(5,'number,lower').substr($img_name,strrpos($img_name,'.'));
	$new_name=date('YmdHis').my_str_shuffle(5,'number,lower').'.jpg';
	$old_img=SRC_PATH.$img_name;
	$new_img=DST_PATH.$new_name;

/*
exif_read_data($old_img)结果如下:
Array
(
    [FileName] => a.jpg
    [FileDateTime] => 1750318340
    [FileSize] => 17175
    [FileType] => 2
    [MimeType] => image/jpeg
    [SectionsFound] => ANY_TAG, IFD0, EXIF
    [COMPUTED] => Array
        (
            [html] => width="536" height="404"
            [Height] => 404
            [Width] => 536
            [IsColor] => 1
            [ByteOrderMotorola] => 1
        )

    [Orientation] => 8
    [Exif_IFD_Pointer] => 318
    [UndefinedTag:0xEA1C] => 
)
*/
	$exif_res=@exif_read_data($old_img);
	if($exif_res===false){
		$size_arr = @getimagesize($old_img);
		if(!is_array($size_arr)){
			exit('图片尺寸获取失败:'.$img_name);
		}
		$w = $size_arr[0];
		$h= $size_arr[1];
		//printr($size_arr);
	}else{
		$w=$exif_res['COMPUTED']['Width'];
		$h=$exif_res['COMPUTED']['Height'];
		//printr($exif_res);
	}
	
	$source = imagecreatefromstring(file_get_contents($old_img));
	switch(array_item($exif_res,'Orientation')){
		case 1: //无翻转
			break;
		case 2: //水平翻转
			imageflip($source,IMG_FLIP_HORIZONTAL);
			break;
		case 3: //旋转180度
			$source = imagerotate($source,180,0);
			break;
		case 4: //垂直翻转
			imageflip($source,IMG_FLIP_VERTICAL);
			break;
		case 5: //顺时针旋转90度+水平翻转
			$source = imagerotate($source,-90,0);
			imageflip($source,IMG_FLIP_HORIZONTAL);
			break;
		case 6: //顺时针旋转90度
			$source = imagerotate($source,-90,0);
			break;
		case 7: //逆时针旋转90度+水平翻转
			$source = imagerotate($source,90,0);
			imageflip($source,IMG_FLIP_HORIZONTAL);
			break;
		case 8: //逆时针旋转90度
			$source = imagerotate($source,90,0);
			break;
		default: //png等无方向属性
	}
	switch(array_item($exif_res,'Orientation')){
		case 5:
		case 6:
		case 7:
		case 8:
			//旋转90度的图片扶正后要宽高值要互换
			$tmp=$w;
			$w=$h;
			$h=$tmp;
			unset($tmp);
			break;
	}
	$src_w=$w;
	$src_h=$h;

	if($w/$h < $width/$height){
		$h=ceil($w*$height/$width);
	}else if($w/$h > $width/$height){
		$w=ceil($width*$h/$height);
	}else{
		//比例一致时,如果原图小于100K则直接复制
		if(filesize($old_img)<100*1024){
			copy($old_img,$new_img);
			return $new_name;
		}
	}
	if($w<$width){
		$width=$w;
		$height=$h;
	}

	//echo $w,'x',$h,'<br>',$width,'x',$height,'<br>';return;
	
	//新建真彩色图像
	$im = imagecreatetruecolor($width, $height);
	//为图像分配颜色
	//$color = imagecolorallocate($im, 255,255,255);
	//从指定坐标开始填充颜色
	//imagefill($im, 0,0, $color);
	//从字符串的图像流中新建图像,可以自动识别文件类型,但是比 imagecreatefromjpeg 等多消耗内存
	//totxt($old_img, FCPATH.'photo.txt', true);
	//$source = imagecreatefromstring(file_get_contents($old_img));
/*
从 x、y 坐标 src_x、src_y 开始,将 src_image 的一部分复制到 dst_image 上,
宽度为 src_width,高度为 src_height。定义的部分将被复制到 x,y 坐标 dst_x 和 dst_y 上。
imagecopy(
    GdImage $dst_image,
    GdImage $src_image,
    int $dst_x,
    int $dst_y,
    int $src_x,
    int $src_y,
    int $src_width,
    int $src_height
): bool

从 src_image 位置(src_x、src_y)开始取出一个宽度为 src_width 高度为 src_height 的矩形区域,
并将其放置在 dst_image 中位置从(dst_x、dst_y)开始宽度为 dst_width 高度为 dst_height 的矩形区域中。
imagecopyresampled(
    GdImage $dst_image,
    GdImage $src_image,
    int $dst_x,
    int $dst_y,
    int $src_x,
    int $src_y,
    int $dst_width,
    int $dst_height,
    int $src_width,
    int $src_height
): bool

输出图象到浏览器或文件
image 由图象创建函数(例如imagecreatetruecolor())返回的 GdImage 对象。
file 文件保存的路径或者已打开的流资源(此方法返回后自动关闭该流资源),如果未设置或为 null,将会直接输出原始图象流。
quality 为可选项,范围从 0(最差质量,文件最小)到 100(最佳质量,文件最大)。默认值(-1)使用 IJG 默认的质量值(大约 75)。
imagejpeg(GdImage $image, resource|string|null $file = null, int $quality = -1): bool
*/
	//执行剪裁(高质量重采样)
	//($src_h-$h)/4 此处是4而不是2的原因:尽量从上边开始剪裁,避免上边剪裁过大,导致头到照片顶部留白太小甚至剪到头
	imagecopyresampled($im, $source, 0,0, $src_w>$w?($src_w-$w)/2:0,$src_h>$h?($src_h-$h)/3:0, $width,$height, $w,$h);
	imagedestroy($source);
	
	//保存到文件
	imagejpeg($im, $new_img, 90);
	imagedestroy($im);
	//exit('ok');
	return $new_name;
}
2025-09-19 星期五 农历七月二十八