使用Canvas实现图像弧形畸变(复刻ImageMagick效果)
Canvas实现ImageMagick风格的图像弧形畸变
我们可以基于逐列旋转绘制的思路,扩展原脚本以支持指定弧形角度,同时保持原图比例,复刻ImageMagick的弧形畸变效果。核心是将原图宽度映射到目标弧形的弧长,高度映射到内外半径的差值,通过控制角度范围实现不同弧度的畸变。
关键改进点
- 支持自定义弧形角度(60°/120°/180°/270°/360°),将角度转换为弧度后控制绘制范围
- 计算弧形弧长与原图宽度的比例,确保图像拉伸/压缩符合预期
- 优化绘制步进值,保证图像细节不丢失
完整实现代码
<canvas id="cv"></canvas> <img id="ig" src="your-image.jpg" style="display:none;" onload="init()"> <script> var cv = document.getElementById('cv'); var ig = document.getElementById('ig'); var ctx = cv.getContext('2d'); /** * 将图像的指定区域绘制为弧形畸变效果 * @param {HTMLImageElement} img - 源图像 * @param {number} cx - 弧形中心X坐标 * @param {number} cy - 弧形中心Y坐标 * @param {number} innerRadius - 弧形内半径 * @param {number} outerRadius - 弧形外半径 * @param {number} arcAngle - 弧形角度(单位:度,支持60/120/180/270/360) * @param {number} startX - 源图像起始X * @param {number} startY - 源图像起始Y * @param {number} endX - 源图像结束X * @param {number} endY - 源图像结束Y */ function drawImageAsArc(img, cx, cy, innerRadius, outerRadius, arcAngle, startX, startY, endX, endY) { // 将角度转换为弧度,计算有效角度范围 const arcRadian = arcAngle * Math.PI / 180; const startAngle = -arcRadian / 2; // 让弧形居中显示 const endAngle = arcRadian / 2; // 计算弧长与原图宽度的比例,确定每弧度对应的图像X偏移 const arcLength = outerRadius * arcRadian; const imgWidth = endX - startX; const xStepPerRadian = imgWidth / arcRadian; // 计算绘制步进值,确保图像细节足够精细 const step = Math.atan2(1, outerRadius); ctx.save(); ctx.translate(cx, cy); let angle = startAngle; while (angle <= endAngle) { ctx.save(); ctx.rotate(angle); ctx.translate(innerRadius, 0); ctx.rotate(-Math.PI / 2); // 旋转图像列使其垂直于弧形半径 // 计算当前角度对应的源图像X位置 const xOffset = (angle - startAngle) * xStepPerRadian; const x = startX + xOffset; // 绘制单列图像,高度对应内外半径差 ctx.drawImage( img, x, startY, 1, endY - startY, // 源图像截取区域 0, 0, 1, outerRadius - innerRadius // 目标绘制区域 ); ctx.restore(); angle += step; } ctx.restore(); } function init() { // 设置画布尺寸,适配弧形大小 cv.width = 600; cv.height = 600; // 参数配置,可根据需求调整 const cx = 300; const cy = 300; const innerRadius = 50; const outerRadius = 250; const arcAngle = 180; // 替换为60/120/270/360可得到对应效果 const startX = 0; const endX = ig.width; const startY = 0; const endY = ig.height; drawImageAsArc(ig, cx, cy, innerRadius, outerRadius, arcAngle, startX, startY, endX, endY); } </script>
代码说明
- 角度范围控制:通过
arcAngle参数指定弧形角度,转换为弧度后计算起始/结束角度,让弧形居中显示。 - 比例适配:计算弧形弧长,将原图宽度按比例映射到弧长上,避免图像出现不合理的拉伸或压缩。
- 逐列绘制逻辑:沿着弧形角度逐步绘制原图的1像素宽列,旋转后贴合弧形半径方向,保证畸变效果自然。
- 参数灵活性:支持自定义内外半径调整弧形粗细,也可指定图像局部区域进行畸变处理。
内容的提问来源于stack exchange,提问作者Dady
相关产品推荐
相关产品推荐

