<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0" />
<title>圆形裁剪</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
padding: 20px;
}
img {
width: 500px;
}
img,
canvas {
outline: 1px solid #999;
}
</style>
</head>
<body>
<img src="./test.jpg" class="origin" alt="" />
<button type="button" class="btn-crop">圆形裁剪</button>
<img class="clip" alt="" />
<script>
const origin = document.querySelector('.origin');
const btnCrop = document.querySelector('.btn-crop');
const clip = document.querySelector('.clip');
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const width = origin.offsetWidth;
const height = origin.offsetHeight;
canvas.width = width * devicePixelRatio;
canvas.height = width * devicePixelRatio;
canvas.style.width = `${100}px`;
canvas.style.height = `${100}px`;
clip.style.width = `${100}px`;
clip.style.height = `${100}px`;
const scalex = origin.naturalWidth / width;
const scaley = origin.naturalHeight / height;
context.drawImage(origin, 0, 0, width, height);
context.beginPath();
context.arc(canvas.width / 2, canvas.height / 2, canvas.width / 2, 0, 2 * Math.PI);
context.clearRect(0, 0, width, height);
context.clip();
let mask = null;
origin.addEventListener('mouseenter', () => {
mask = document.createElement('div');
const { left, top } = origin.getBoundingClientRect();
mask.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: ${canvas.offsetWidth}px;
height: ${canvas.offsetHeight}px;
border-radius: 50%;
background-color: rgba(0, 0, 0, 0.5);
translate:${left}px ${top}px;
will-change: translate;
z-index: 999;
pointer-events: none;
`;
document.body.append(mask);
});
origin.addEventListener('mouseleave', () => {
if (mask) {
document.body.removeChild(mask);
}
})
window.onmousemove = (e) => {
let x = e.clientX - origin.offsetLeft - canvas.offsetWidth / 2;
let y = e.clientY - origin.offsetTop - canvas.offsetHeight / 2;
x = Math.max(x, 0);
y = Math.max(y, 0);
x = Math.min(x, origin.offsetWidth - origin.offsetLeft - canvas.offsetWidth / 2);
y = Math.min(y, origin.offsetHeight - origin.offsetTop - canvas.offsetHeight / 2);
if (mask) {
mask.style.translate = `${e.clientX - canvas.offsetWidth / 2}px ${
e.clientY - canvas.offsetHeight / 2
}px`;
}
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(
origin,
x * scalex,
y * scaley,
canvas.offsetWidth * scalex,
canvas.offsetHeight * scaley,
0,
0,
canvas.offsetWidth * scalex * devicePixelRatio,
canvas.offsetHeight * scaley * devicePixelRatio
);
};
origin.addEventListener('click', () => {
// clip.src = canvas.toDataURL();
canvas.toBlob(
(blob) => {
const url = URL.createObjectURL(blob);
clip.src = url;
// open(url);
// URL.revokeObjectURL(url);
},
'image/jpeg',
1
);
});
document.body.append(canvas);
</script>
</body>
</html>