我正在尝试在图片周围绘制一个圆形倒计时(arc
会将其end angle
降低到另一个arc
以上,这仍然是静态的。
在绘制静态和动态弧以将图像绘制到其中之后,我必须clip
。
但问题是,图像正在进入动态弧(所以我们没有完全看到它)。
这是代码和JsFiddle:
<canvas id="test" width="230px", height="230px"></canvas>
var ctx = document.getElementById('test').getContext("2d");
var img = new Image();
img.addEventListener('load', function(e) {
ctx.beginPath();
ctx.arc(115, 115, 100, 0, Math.PI * 2, true);
ctx.closePath();
ctx.lineWidth = 15;
ctx.strokeStyle = 'back';
ctx.stroke();
ctx.beginPath();
ctx.arc(115, 115, 100, 0, 1*Math.PI, true);
ctx.closePath();
ctx.lineWidth = 15;
ctx.strokeStyle = 'red';
ctx.stroke();
ctx.clip();
ctx.drawImage(this, 15, 15, 200, 200);
}, true);
img.src="https://si0.twimg.com/profile_images/3309741408/eff94615a3653c01a9d5a178ced7fbb5.jpeg";
更新
以下是我正在寻找的内容非常接近:JsFiddle updated,除了红色arc
以非常糟糕的方式出现...
答案 0 :(得分:3)
你非常亲密,只需要改变一些事情的命令(我希望我理解你的意图正确):
我建议首先用一个完整的圆圈进行裁剪,因为这不会遮挡在它上面绘制的内容(如果你以后剪辑,你也可以剪切圆弧 - 除非你想这样做)。
重置剪贴蒙版结果有点“不稳定”,即。设置一个新路径和一个覆盖整个画布的矩形。因此,目前在这种情况下更好的选择是依靠save
/ restore
方法重置它:
/// backup current state of canvas
ctx.save();
/// create clipping mask, a full circle
ctx.beginPath();
ctx.arc(115, 115, 100, 0, Math.PI * 2);
ctx.closePath();
ctx.clip();
/// then draw the image that you want to clip
ctx.drawImage(this, 15, 15, 200, 200);
/// remove clipping by restoring canvas state to previous
ctx.restore();
现在将图像剪切成圆形,您可以绘制圆弧,而不考虑或重新计算与图像相关的线宽等,因为它们不受剪裁限制:
/// draw the arcs on top
ctx.beginPath();
ctx.arc(115, 115, 100, 0, Math.PI * 2, true);
ctx.lineWidth = 15;
ctx.strokeStyle = 'red';
ctx.stroke();
ctx.beginPath();
ctx.arc(115, 115, 100, 0, 1*Math.PI, true);
ctx.lineWidth = 15;
ctx.strokeStyle = 'blue';
ctx.stroke();
<强> MODIFIED FIDDLE HERE 强>
答案 1 :(得分:2)
您可以使用context.save / context.restore来控制裁剪活动
这是一种方法:
// Outer circle
ctx.beginPath();
ctx.arc(150, 150, 40, 0, 2 * PI, false);
ctx.closePath();
ctx.lineWidth=20;
ctx.strokeStyle="black";
ctx.stroke();
// Inner sweeping arc
ctx.beginPath();
ctx.arc(150, 150, 40, startRadians, endRadians, false);
ctx.lineWidth = 10;
ctx.strokeStyle = 'red';
ctx.stroke();
// Clipped avatar
ctx.save();
ctx.beginPath();
ctx.arc(150, 150, 30, 0, 2 * PI, false);
ctx.closePath();
ctx.clip();
ctx.drawImage(avatar, 0, 0, avatar.width, avatar.height, 150-40, 150-40, 80, 80);
ctx.restore();
这是代码和小提琴:http://jsfiddle.net/m1erickson/j96yy/
$(function() {
var avatarUrl = 'https://dl.dropboxusercontent.com/u/139992952/stackoverflow/avatar.jpg';
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var fps = 60;
window.requestAnimFrame = (function(callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / fps);
};
})();
// Set context styles
ctx.strokeStyle = '#ff9944';
ctx.lineCap = 'round';
// Set var's to control arc
var PI = Math.PI;
var startRadians = -PI / 2;
var endRadians = -PI / 2;
var tickRadians = 2 * PI / 60 / 2; // 60 ticks per circle
var continue_animation = true;
// Load avatar image, then animate
var avatar = loadImage(avatarUrl, animate);
// Compute size and location of the avatar.
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = canvas.width * 0.33;
// Animate an arc inside a circle
function animate() {
// Update
endRadians += tickRadians;
if (endRadians > 2 * PI) {
continue_animation = false;
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Outer circle
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, 2 * PI, false);
ctx.closePath();
ctx.lineWidth = radius / 2;
ctx.strokeStyle = '#444444';
ctx.stroke();
// Inner sweeping arc
ctx.beginPath();
ctx.arc(centerX, centerY, radius, startRadians, endRadians, false);
ctx.lineWidth = radius / 4;
ctx.strokeStyle = calcArcStateColor(endRadians);
ctx.stroke();
// Clipped avatar
ctx.save();
ctx.beginPath();
ctx.arc(centerX, centerY, radius * 0.75, 0, 2 * PI, false);
ctx.closePath();
ctx.clip();
ctx.drawImage(avatar, 0, 0, avatar.width, avatar.height, centerX - radius, centerY - radius, radius * 2, radius * 2);
ctx.restore();
// Request new frame
if (continue_animation) {
requestAnimFrame(animate);
}
}
$('#go').click(function() {
endRadians = -PI / 2;
continue_animation = true;
animate();
});
animate();
});
function loadImage(url, callback) {
var img = new Image();
img.onload = function() {
if (callback) callback();
};
img.src = url;
return img;
}
function calcArcStateColor(radians) {
if (radians > Math.PI * 1.75) return '#00DD44';
else if (radians > Math.PI * 1.00) return '#FFDD44';
else if (radians > Math.PI * 0.25) return '#FF8844';
else return '#FF4444';
}
body {
background-color: ivory;
padding: 20px;
}
canvas {
border: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css" rel="stylesheet" />
<button id="go">Animate</button><br />
<canvas id="canvas" width="180" height="180"></canvas>
答案 2 :(得分:0)
在剪辑之前保存您的上下文,并在您想要取消剪辑所需的时间使用恢复方法