console
!function () {
"use strict";
var dotChoose = document.getElementById("dot");
var rectChoose = document.getElementById("rect");
var picChoose = document.getElementById("pic");
var countChoose = document.getElementById("count");
var a = document.createElement("A");
a.href = window.location.href;
var ret = {},
seg = a.search.replace(/^\?/, '').split("&"),
len = seg.length,
i = 0, s;
for (; i < len; i++) {
if (!seg[i]) continue;
s = seg[i].split("=");
ret[s[0]] = s[1];
}
if ('dot' in ret) {
if (ret.dot === "true") dotChoose.setAttribute("checked", "");
else dotChoose.removeAttribute("checked");
}
if ('rect' in ret) {
if (ret.rect === "true") rectChoose.setAttribute("checked", "");
else rectChoose.removeAttribute("checked");
}
if ('pic' in ret) {
if (ret.pic === "true") picChoose.setAttribute("checked", "");
else picChoose.removeAttribute("checked");
}
var RAF = (function () {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
var hasDot = dotChoose.checked,
hasRect = rectChoose.checked,
hasPic = picChoose.checked,
count = getSelected();
dotChoose.onchange = function () { hasDot = this.checked; render(); };
rectChoose.onchange = function () { hasRect = this.checked; render(); };
picChoose.onchange = function () { hasPic = this.checked; render(); };
countChoose.onchange = function () {
count = getSelected();
idots = rectsplit(count, dots[0], dots[1], dots[2], dots[3]);
ndots = rectsplit(count, dots[0], dots[1], dots[2], dots[3]);
render();
};
function getSelected() {
var ops = countChoose.getElementsByTagName("OPTION"), op;
for (var i = 0; i < ops.length; i++) {
op = ops[i];
if (op.selected) return +op.value;
}
}
var canvas = document.getElementById("cas");
var ctx = canvas.getContext("2d");
var dots = [];
var idots, ndots;
var img = new Image();
img.src = "http://whxaxes.github.io/canvas-test/src/Funny-demo/transform/img/test.jpg";
img.onload = function () {
var img_w = img.width / 2;
var img_h = img.height / 2;
var left = (canvas.width - img_w) / 2;
var top = (canvas.height - img_h) / 2;
img.width = img_w;
img.height = img_h;
dots = [
{ x: left, y: top },
{ x: left + img_w, y: top },
{ x: left + img_w, y: top + img_h },
{ x: left, y: top + img_h }
];
idots = rectsplit(count, dots[0], dots[1], dots[2], dots[3]);
ndots = rectsplit(count, dots[0], dots[1], dots[2], dots[3]);
render();
};
var area = {};
window.onmousemove = function (e) {
if (!ndots) return;
e = e || window.event;
area = {
x: e.clientX - canvas.offsetLeft + document.body.scrollLeft + document.documentElement.scrollLeft,
y: e.clientY - canvas.offsetTop + document.body.scrollTop + document.documentElement.scrollTop
};
};
var maxDis = 140,
focallength = 250;
animate();
function animate() {
var len = ndots ? ndots.length : 0,
ax = area.x,
ay = area.y,
d, c, scale, dis, xc, yc;
while (len) {
len--;
d = ndots[len];
if (!d.ix) {
d.ix = d.x;
d.iy = d.y;
d.z = 0;
}
if (ax == null || ay == null) break;
xc = d.ix - ax;
yc = d.iy - ay;
dis = Math.sqrt(xc * xc + yc * yc);
d.ez = (maxDis - dis) * 2;
if (d.ez >= 0) {
d.ax = ax;
d.ay = ay;
} else {
d.ez = 0;
}
c = d.ez - d.z;
d.z += c * 0.1;
scale = focallength / (focallength + d.z);
d.x = (d.ax || ax) + (d.ix - (d.ax || ax)) / scale;
d.y = (d.ay || ay) + (d.iy - (d.ay || ay)) / scale;
}
render();
RAF(animate);
}
function render() {
if (!ndots) return;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillRect(dots[0].x, dots[0].y, img.width, img.height)
ctx.lineWidth = 3;
ctx.strokeStyle = "#fff";
ndots.forEach(function (d, i) {
var dot1 = ndots[i];
var dot2 = ndots[i + 1];
var dot3 = ndots[i + count + 2];
var dot4 = ndots[i + count + 1];
var idot1 = idots[i];
var idot2 = idots[i + 1];
var idot3 = idots[i + count + 2];
var idot4 = idots[i + count + 1];
if (dot2 && dot3 && i % (count + 1) < count) {
renderImage(idot3, dot3, idot2, dot2, idot4, dot4);
renderImage(idot1, dot1, idot2, dot2, idot4, dot4);
}
if (hasDot) {
ctx.save();
ctx.fillStyle = "red";
ctx.fillRect(d.x - 1, d.y - 1, 2, 2);
ctx.restore();
}
});
}
function renderImage(arg_1, _arg_1, arg_2, _arg_2, arg_3, _arg_3) {
function matrix2() {
function getMatrix(arg_1, _arg_1, arg_2, _arg_2, arg_3, _arg_3) {
var arr1 = [arg_1.x, arg_1.y, 1, _arg_1.x];
var arr2 = [arg_2.x, arg_2.y, 1, _arg_2.x];
var arr3 = [arg_3.x, arg_3.y, 1, _arg_3.x];
var result = equation(arr1, arr2, arr3);
arr1[3] = _arg_1.y;
arr2[3] = _arg_2.y;
arr3[3] = _arg_3.y;
var result2 = equation(arr1, arr2, arr3);
var a = result.x;
var c = result.y;
var e = result.z;
var b = result2.x;
var d = result2.y;
var f = result2.z;
return {
a: a,
b: b,
c: c,
d: d,
e: e,
f: f
};
}
function equation(arr1, arr2, arr3) {
var a1 = +arr1[0];
var b1 = +arr1[1];
var c1 = +arr1[2];
var d1 = +arr1[3];
var a2 = +arr2[0];
var b2 = +arr2[1];
var c2 = +arr2[2];
var d2 = +arr2[3];
var a3 = +arr3[0];
var b3 = +arr3[1];
var c3 = +arr3[2];
var d3 = +arr3[3];
var m1 = c1 - (b1 * c2 / b2);
var m2 = c2 - (b2 * c3 / b3);
var m3 = d2 - (b2 * d3 / b3);
var m4 = a2 - (b2 * a3 / b3);
var m5 = d1 - (b1 * d2 / b2);
var m6 = a1 - (b1 * a2 / b2);
var x = ((m1 / m2) * m3 - m5) / ((m1 / m2) * m4 - m6);
var z = (m3 - m4 * x) / m2;
var y = (d1 - a1 * x - c1 * z) / b1;
return {
x: x,
y: y,
z: z
}
}
return {
getMatrix: getMatrix,
equation: equation
};
}
let matrix = matrix2()
ctx.save();
ctx.beginPath();
ctx.moveTo(_arg_3.x, _arg_3.y);
ctx.lineTo(_arg_1.x, _arg_1.y);
ctx.lineTo(_arg_2.x, _arg_2.y);
if (hasRect) ctx.stroke();
ctx.closePath();
ctx.clip();
var result;
if (hasPic) {
if (arg_1.x !== _arg_1.x || arg_1.y !== _arg_1.y || arg_2.x !== _arg_2.x || arg_2.y !== _arg_2.y || arg_3.x !== _arg_3.x || arg_3.y !== _arg_3.y) {
result = matrix.getMatrix(arg_1, _arg_1, arg_2, _arg_2, arg_3, _arg_3);
ctx.transform(result.a, result.b, result.c, result.d, result.e, result.f);
}
ctx.drawImage(img, idots[0].x, idots[0].y, img.width, img.height);
}
ctx.restore();
}
function rectsplit(n, a, b, c, d) {
var ad_x = (d.x - a.x) / n;
var ad_y = (d.y - a.y) / n;
var bc_x = (c.x - b.x) / n;
var bc_y = (c.y - b.y) / n;
var ndots = [];
var x1, y1, x2, y2, ab_x, ab_y;
for (var i = 0; i <= n; i++) {
x1 = a.x + ad_x * i;
y1 = a.y + ad_y * i;
x2 = b.x + bc_x * i;
y2 = b.y + bc_y * i;
for (var j = 0; j <= n; j++) {
ab_x = (x2 - x1) / n;
ab_y = (y2 - y1) / n;
ndots.push({
x: x1 + ab_x * j,
y: y1 + ab_y * j
})
}
}
return ndots;
}
}()
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>图像3d变形</title>
<style>
body{-moz-user-select: none;}
#cas{
position: absolute;
top: 80px;
left: 0;
right: 0;
margin: auto;
border: 1px solid;
}
.tips{text-align: center;margin: 15px 0;}
.control{ text-align: center; }
</style>
</head>
<body onselectstart="return false">
<div class="tips">Tips:鼠标移至图片处</div>
<div class="control">
<input type="checkbox" id="dot"/><label for="dot">点</label>
<input type="checkbox" id="rect" checked/><label for="rect">方格</label>
<input type="checkbox" id="pic" checked/><label for="pic">贴图</label>
<select name="count" id="count">
<option value="5" selected>5</option>
<option value="15">15</option>
<option value="30">30</option>
</select>
</div>
<canvas id="cas" width="1000" height="600">
亲,你滴浏览器太out啦,换一个吧
</canvas>
</body>
</html>