JS 判断空值但 0 不算空
直接用 !value 的问题:
if (!value) { ... }
// 会把 0、false、NaN、''、null、undefined 全算空
// 经常误伤数字 0
正确写法 —— 只排除 null、undefined、空字符串:
if (value == null || value === '') {
// 空值
}
value == null 会同时匹配 null 和 undefined(宽松相等),不会匹配 0 或 false。
封装函数
function isEmpty(value) {
return value == null || value === '';
}
isEmpty(null) // true
isEmpty(undefined) // true
isEmpty('') // true
isEmpty(0) // false
isEmpty(false) // false
isEmpty([]) // false
isEmpty({}) // false
同时排除全空格字符串
function isEmpty(value) {
return value == null ||
(typeof value === 'string' && value.trim() === '');
}
isEmpty(' ') // true
isEmpty(' a ') // false
Canvas 滚轮缩放图片
核心思路:记录 scale(缩放比)和 offsetX/Y(画布偏移量),每次绘制时先平移再缩放。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<style>
html, body { margin: 0; height: 100%; overflow: hidden; background: #111; }
canvas { display: block; width: 100vw; height: 100vh; cursor: grab; }
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const img = new Image();
img.src = "https://picsum.photos/1200/800";
let scale = 1;
let offsetX = 0;
let offsetY = 0;
img.onload = () => draw();
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save();
ctx.translate(offsetX, offsetY);
ctx.scale(scale, scale);
ctx.drawImage(img, 0, 0);
ctx.restore();
}
// 滚轮缩放
canvas.addEventListener("wheel", (e) => {
e.preventDefault();
const mouseX = e.offsetX;
const mouseY = e.offsetY;
// 鼠标在图片坐标系中的位置(缩放前)
const x = (mouseX - offsetX) / scale;
const y = (mouseY - offsetY) / scale;
const zoom = e.deltaY < 0 ? 1.1 : 0.9;
scale *= zoom;
scale = Math.max(0.1, Math.min(scale, 20)); // 限制范围
// 缩放后修正偏移,保证鼠标所在点不漂移
offsetX = mouseX - x * scale;
offsetY = mouseY - y * scale;
draw();
}, { passive: false });
// 拖拽移动
let dragging = false;
let lastX = 0, lastY = 0;
canvas.addEventListener("mousedown", (e) => {
dragging = true;
lastX = e.clientX;
lastY = e.clientY;
canvas.style.cursor = "grabbing";
});
window.addEventListener("mousemove", (e) => {
if (!dragging) return;
offsetX += e.clientX - lastX;
offsetY += e.clientY - lastY;
lastX = e.clientX;
lastY = e.clientY;
draw();
});
window.addEventListener("mouseup", () => {
dragging = false;
canvas.style.cursor = "grab";
});
window.addEventListener("resize", () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
draw();
});
</script>
</body>
</html>
鼠标中心缩放原理
缩放时要保持鼠标位置不变,关键公式:
// 缩放前:鼠标在图片坐标系的位置
x = (mouseX - offsetX) / scale
// 缩放后:offsetX 要满足 mouseX = x * newScale + newOffsetX
newOffsetX = mouseX - x * newScale
即先算出鼠标对应图片上的点坐标,缩放后重新反算偏移量。不做这一步,图片会向左上角方向漂移。
{ passive: false } 的作用
wheel 事件的 e.preventDefault() 阻止页面滚动,必须在监听器选项里显式传 { passive: false },否则浏览器忽略 preventDefault() 并输出警告。
