Изображение холста с закругленными углами
Я использую этот сценарий на своем веб-сайте и не знаю, как вывести холст со скругленными углами.
Это код, который рисует изображение
ctx.drawImage(image, cropLeft, cropTop, wid-2*cropLeft, hei-2*cropTop, 0, 0, newWidth, newHeight);
Я читал некоторые учебники, используя функции arc() или arcTo(), но ни в одном из них мы не используем изображение в качестве объекта.
ОБНОВЛЕНИЕ1: Я вижу, что drawimage() имеет только следующие параметры для рисования: • Изображения того же размера и композиции, что и оригинал • Изображения, которые изменены по размеру от оригинала • Изображения, обрезанные из оригинала
Итак, я думаю, что невозможно рисовать изображения с закругленными углами через холст..
2 ответа
Ты можешь использовать context.clip()
нарисовать изображение, которое обрезается внутри скругленного прямоугольника
Сначала нарисуйте прямоугольник с закругленными углами (не нужно обводить или заливать):
// draw a rounded rectangle
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.lineTo(x + width - radius, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
ctx.lineTo(x + width, y + height - radius);
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
ctx.lineTo(x + radius, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
ctx.closePath();
Затем вызовите context.clip, который приведет к обрезанию всех будущих рисунков внутри прямоугольника.
ctx.clip();
Наконец, нарисуйте ваше изображение внутри этого прямоугольника, и ваше изображение будет обрезано вокруг.
ctx.drawImage(img,10,10,102,77);
Вот пример кода и скрипка: http://jsfiddle.net/m1erickson/FLaee/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
#canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var img=new Image();
img.onload=function(){
ctx.save();
roundedImage(10,10,102,77,10);
ctx.clip();
ctx.drawImage(img,10,10,102,77);
ctx.restore();
}
img.src="https://dl.dropboxusercontent.com/u/139992952/stackru/sky-bg2.jpg";
function roundedImage(x,y,width,height,radius){
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.lineTo(x + width - radius, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
ctx.lineTo(x + width, y + height - radius);
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
ctx.lineTo(x + radius, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
ctx.closePath();
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
Проблема с решением clip() заключается в том, что Chrome будет отображать его с границами без сглаживания, как показано в этом вопросе.
Одним из решений было бы сделать это с globalCompositeOperation, как говорит Даниэль в своем ответе:
//set-up - probably only needs to be done once
var scratchCanvas = document.createElement('canvas');
scratchCanvas.width = 100;
scratchCanvas.height = 100;
var scratchCtx = scratchCanvas.getContext('2d');
//drawing code
scratchCtx.clearRect(0, 0, scratchCanvas.width, scratchCanvas.height);
scratchCtx.globalCompositeOperation = 'source-over'; //default
//Do whatever drawing you want. In your case, draw your image.
scratchCtx.drawImage(imageToCrop, ...);
//As long as we can represent our clipping region as a single path,
//we can perform our clipping by using a non-default composite operation.
//You can think of destination-in as "write alpha". It will not touch
//the color channel of the canvas, but will replace the alpha channel.
//(Actually, it will multiply the already drawn alpha with the alpha
//currently being drawn - meaning that things look good where two anti-
//aliased pixels overlap.)
//
//If you can't represent the clipping region as a single path, you can
//always draw your clip shape into yet another scratch canvas.
scratchCtx.fillStyle = '#fff'; //color doesn't matter, but we want full opacity
scratchCtx.globalCompositeOperation = 'destination-in';
scratchCtx.beginPath();
scratchCtx.arc(50, 50, 50, 0, 2 * Math.PI, true);
scratchCtx.closePath();
scratchCtx.fill();
//Now that we have a nice, cropped image, we can draw it in our
//actual canvas. We can even draw it over top existing pixels, and
//everything will look great!
ctx.drawImage(scratchCanves, ...);