Трюк понимает, как масштаб изменяет ряд переменных. Во-первых, он изменяет, какая часть исходного изображения видна на холсте. Затем это в сочетании с желаемой центральной точкой масштабирования влияет на то, где на изображении мы должны начать рисовать.
С масштабом 1,0 количество пикселей отображаемого исходного изображения равно числу пикселей, которые имеет холст dst. I.e, если холст 150x150, мы можем видеть 150x150 входных пикселей. Если, однако, масштаб равен 2,0, то мы хотим сделать вещи в 2 раза больше. Это означает, что мы хотим отображать только 75x75 пикселей изображения src на 150x150 пикселях dst canvas. Аналогично, если мы хотим рисовать в масштабе 0,5, мы должны ожидать увидеть 300x300 пикселей изображения src, отображаемого в 150x150 dst canvas. Возможно, теперь вы можете видеть взаимосвязь между масштабом и размером холста.
Имея это в виду, мы можем определить, какую часть изображения src мы хотим видеть. Это прямо вперед:
var srcWidth = canvas.width/scale;
var srcHeight = canvas.height/scale;
Теперь, когда мы знаем, как большая часть изображения будет показано ниже, мы можем приступить к определению, где в изображении мы должны начать рисовать с.Поскольку мы имеем заданную центральную точку для масштабирования, мы знаем, что эта точка всегда должна оставаться в центре холста.
Если мы удалим масштабирование из уравнения и используем цифры из ранее, мы можем видеть, что мы хотим отображать 150x150 пикселей изображения src и что нам нужно будет начать рисовать 75 пикселей выше и слева от нашего центра -точка. При этом вы получите 150x150 пикселей исходного изображения и поместите нашу центральную точку справа в середину холста.
Если мы затем рассмотрим масштабирование, мы знаем, что мы не всегда будем рисовать 150x150 пикселей изображения src, а это означает, что мы не можем просто слепо запустить 75 пикселей слева и выше нашей центральной точки - нам придется масштабировать эти 75 пикселей. Поскольку эти 75 пикселей равны половине ширины и половине высоты части изображения, которую мы будем отображать, мы можем определить точку, с которой начнем рисовать изображение, разделив srcWidth и srcHeight на 2 и затем вычитая это значение из центральной точки.
Это дает следующее выражение:
ctx.drawImage(image, imgCenterX-(srcWidth/2), imgCenterY-(srcHeight/2), srcWidth, srcHeight, 0,0, canvas.width, canvas.height);
Когда я положил обе эти вместе в образец функционирования, я закончился вверх с этим:
<!DOCTYPE html>
<html>
<head>
<script>
"use strict";
var imgOriginX = 182, imgOriginY = 66;
function byId(id,parent){return (parent == undefined ? document : parent).getElementById(id);}
window.addEventListener('load', onDocLoaded, false);
function onDocLoaded()
{
var targetCanvas = byId('canvas3');
var srcImage = byId('img1');
drawImageScaled(targetCanvas, srcImage, imgOriginX, imgOriginY)
drawCrosshair(byId('canvas3'));
byId('scaleSlider').addEventListener('input', onScaleSliderChange, false);
}
/*
code for scaling an image about an arbitrary point
*/
// canvas - target canvas element
// image - target canvas element
// imgCenterX - x coord of point of scaling centre-point (unit: pixels)
// imgCenterY - y coord of point of scaling centre-point (unit: pixels)
// scale - 1.0 = 100%
function drawImageScaled(canvas, image, imgCenterX, imgCenterY, scale)
{
if (scale === undefined)
scale = 1.0;
var ctx = canvas.getContext('2d');
ctx.clearRect(0,0,canvas.width,canvas.height);
var srcWidth = canvas.width/scale;
var srcHeight = canvas.height/scale;
ctx.drawImage(image, imgCenterX-(srcWidth/2), imgCenterY-(srcHeight/2), srcWidth, srcHeight, 0,0, canvas.width, canvas.height);
}
function drawCrosshair(canvas)
{
var ctx = canvas.getContext('2d');
var width, height;
width = canvas.width;
height = canvas.height;
ctx.save();
ctx.beginPath();
ctx.moveTo(width/2, 0);
ctx.lineTo(width/2, height);
ctx.moveTo(0, height/2);
ctx.lineTo(width, height/2);
ctx.closePath();
ctx.strokeStyle = "red";
ctx.stroke();
ctx.restore();
}
function onScaleSliderChange(evt)
{
var curValue = this.value;
var scale = curValue/100;
var tgt, src;
tgt = byId('canvas3');
src = byId('img1');
drawImageScaled(tgt, src, imgOriginX, imgOriginY, scale);
drawCrosshair(tgt);
}
</script>
<style>
input[type=range]
{
width: 18px;
height: 122px;
-webkit-appearance: slider-vertical;
}
canvas
{
border: solid 1px #888;
}
</style>
</head>
<body>
<img id='img1' src='http://s4.postimg.org/r970hc9e5/meme_faces_rage_wallpaper_1.jpg'/>
<hr>
<canvas id='canvas3' width=150 height=150>Canvas not supported. :(</canvas>
<input id='scaleSlider' type="range" class="scale-slider js-scaleSlider" min="0" max="200" value="100" orient="vertical"/>
</body>
</html>
Если все, что вам нужно сделать, это увеличение +/- в точке на изображении, то вам не нужно преобразовать матрицу. Ознакомьтесь с этим объяснением: http://stackoverflow.com/questions/27339747/zoom-and-pan-in-animated-html5-canvas/27340533#27340533 – markE
@markE Я пробовал реализацию, упомянутую в приведенной ссылке Я создал этот пост. Я обновил кодировщик, и вы увидите, что это тот же результат, что и предыдущий (теперь он прокомментирован). – theOneWhoKnocks
Я отправил ответ, используя 'context.drawImage', чтобы нарисовать глаз вашего мема в центре и увеличить его на холсте. Удачи с вашим проектом! :-) – markE