Как сделать сглаживание клипов () ребер в html5 canvas под Chrome Windows? - PullRequest
30 голосов
/ 02 марта 2012

Я использую функцию clip () на холсте.

Результаты: using canvas clip in various browsers

Как вы можете видеть, версия Chrome имеет ужасные неровности / сглаживание по краям.Как это исправить?

Код для воспроизведения:

http://jsfiddle.net/ZRA76/:

<canvas id="test" width="300" height="300"></canvas>​

<script type="text/javascript">
    cv = document.getElementById("test");
    ctx = cv.getContext("2d");

    var im = new Image();
    im.onload = function () {
        ctx.beginPath();
        ctx.arc(110, 110, 100, 0, 2*Math.PI, true);
        ctx.clip();
        ctx.drawImage(im, 0, 0);
    }
    im.src = "http://placekitten.com/300/300";
</script>

Ответы [ 5 ]

24 голосов
/ 13 декабря 2012

Если вы делаете сложное многоуровневое рисование, вы можете использовать globalCompositeOperation для эмуляции отсечения во втором, чистом холсте.Затем вы можете использовать drawImage, чтобы скопировать рабочий холст обратно в исходный холст.Я не могу гарантировать эффективность этого подхода, но я знаю, что это единственный способ получить то, что вы хотите.

//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(scratchCanvas, ...);

Причина, по которой мы делаем это на пустом месте, заключается в том, что пункт назначения являетсядовольно разрушительная операция.Если вы уже нарисовали некоторые вещи на главном холсте (возможно, вы положили хороший градиент на заднем плане), а затем хотите нарисовать обрезанное изображение, обрезной круг также обрежет все, что вы уже нарисовали.Конечно, если ваша конкретная ситуация проще (возможно, ВСЕ, что вы хотите нарисовать, это обрезанное изображение), то вы можете отказаться от скретча.

Вы можете поиграть с различными режимами обрезки на myдемонстрационная страница .Нижний ряд (с градиентами) не слишком полезен для вас, но верхний ряд (с кружком и квадратом) гораздо более актуален.

edit

Ой, я случайно раздвоил твой JSFiddle , чтобы продемонстрировать технику.

12 голосов
/ 13 сентября 2012

Мое исправление заключается в том, чтобы нарисовать тонкий (2 пикселя) белый штрих на том же радиусе после рисования изображения. Он хорошо скрывает псевдонимы и отлично смотрится во всех браузерах.

5 голосов
/ 31 июля 2012

Я сталкивался с той же проблемой с Chrome и clip ().

В моих обстоятельствах я достиг лучшей совместимости с браузером, установив холст globalCompositeOperation.

context.globalCompositeOperation = 'source-atop';

Итак, нарисуйте свою форму, круг в этом случае. Затем переключитесь на «source-atop» и нарисуйте изображение своего котенка.

Обратите внимание, что это быстрое решение для базового рисования и предполагает пустой холст. Предыдущий рисунок на холсте повлияет на ваш клип.

2 голосов
/ 02 марта 2012

из ответов на Можно ли отключить сглаживание для элемента HTML ? , похоже, что это зависит от браузера. Это даже активный отчет об ошибке в проекте Google Chrome Chrome. Извините, но похоже, вам сейчас не повезло.

0 голосов
/ 31 марта 2012

Используйте клип SVG.Работает как шарм, но не очень удобен в использовании.

...