, !!
Blindman67, , .
HTML
<div id="main"></div>
<br>
<span id="screen" style="border: 2px solid red;"></span>
<span id="world" style="border: 2px solid blue;"></span>
<button id="btnRotate">ROTATE!</button>
JS
var canvas = null;
var ctx = null;
var gridStart = null;
var gridEnd = null;
var gridStepMajor = null;
var gridStepMinor = null;
var minorCol = null;
var majorCol = null;
var minorWidth = null;
var majorWidth = null;
var scale = 1;
var rotation = 45;
var painting = false,
lastX = 0,
lastY = 0,
lineThickness = 1;
var matrix = [1, 0, 0, 1, 0, 0];
var invMatrix = [1, 0, 0, 1];
function createMatrix(x, y, scale, rotation)
{
rotation = rotation * (Math.PI / 180);
var m = matrix;
var im = invMatrix;
m[3] = m[0] = Math.cos(rotation) * scale;
m[2] = -(m[1] = Math.sin(rotation) * scale);
m[4] = x;
m[5] = y;
cross = m[0] * m[3] - m[1] * m[2];
im[0] = m[3] / cross;
im[1] = -m[1] / cross;
im[2] = -m[2] / cross;
im[3] = m[0] / cross;
}
function toWorld(x,y)
{
var xx, yy, m;
m = invMatrix;
xx = x - matrix[4];
yy = y - matrix[5];
return{
x: parseInt(xx * m[0] + yy * m[2], 10) ,
y: parseInt(xx * m[1] + yy * m[3], 10)
}
}
var mouseWorldPos = toWorld(0, 0);
function draw()
{
gridStart = 0;
gridEnd = canvas.width;
gridStepMajor = canvas.width / 10;
gridStepMinor = canvas.width / 20;
minorCol = "#999";
majorCol = "#000";
minorWidth = 1;
majorWidth = 3;
ctx.lineWidth = 2;
ctx.beginPath();
ctx.strokeStyle = majorCol ;
ctx.lineWidth = majorWidth;
for(i = gridStart; i <= gridEnd; i+= gridStepMajor)
{
ctx.moveTo(gridStart, i);
ctx.lineTo(gridEnd, i);
ctx.moveTo(i, gridStart);
ctx.lineTo(i, gridEnd);
}
ctx.stroke();
ctx.strokeStyle = minorCol;
ctx.lineWidth = minorWidth;
for(i = gridStart+gridStepMinor; i < gridEnd; i+= gridStepMinor)
{
ctx.moveTo(gridStart, i);
ctx.lineTo(gridEnd, i);
ctx.moveTo(i, gridStart);
ctx.lineTo(i, gridEnd);
}
ctx.stroke();
ctx.fillStyle = "red";
ctx.strokeStyle = "red";
ctx.lineWidth = 4;
ctx.beginPath();
ctx.arc(50, 50, 6, 0, Math.PI*2);
ctx.fill();
}
function demo()
{
canvas = document.createElement("canvas");
canvas.width = 500;
canvas.height = 300;
canvas.ctx = canvas.getContext("2d");
ctx = canvas.ctx;
$("#main").append(canvas);
draw();
}
var timer = 0;
var timerStep = 0.5;
var seconds = 15;
function rotate()
{
timer += timerStep;
var cw = canvas.width / 2;
var ch = canvas.height / 2;
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, canvas.width, canvas.height);
createMatrix(cw, ch -50, scale, timer);
var m = matrix;
ctx.setTransform(m[0], m[1], m[2], m[3], m[4], m[5]);
draw();
if(timer <= rotation )
{
requestAnimationFrame(rotate);
}
}
$(document).ready(function()
{
demo();
$(canvas).mousedown(function(e)
{
painting = true;
ctx.fillStyle = "#0000FF";
mouseWorldPos = toWorld(e.pageX, e.pageY);
lastX = mouseWorldPos.x;
lastY = mouseWorldPos.y;
});
$(canvas).mousemove(function(e)
{
$("#screen").text("X: " + e.pageX + " - Y:" + e.pageY);
mouseWorldPos = toWorld(e.pageX, e.pageY);
$("#world").text("X: " + mouseWorldPos.x + " - Y:" + mouseWorldPos.y);
if (painting)
{
mouseX = mouseWorldPos.x;
mouseY = mouseWorldPos.y;
var x1 = mouseX,
x2 = lastX,
y1 = mouseY,
y2 = lastY;
var steep = (Math.abs(y2 - y1) > Math.abs(x2 - x1));
if (steep){
var x = x1;
x1 = y1;
y1 = x;
var y = y2;
y2 = x2;
x2 = y;
}
if (x1 > x2) {
var x = x1;
x1 = x2;
x2 = x;
var y = y1;
y1 = y2;
y2 = y;
}
var dx = x2 - x1,
dy = Math.abs(y2 - y1),
error = 0,
de = dy / dx,
yStep = -1,
y = y1;
if (y1 < y2) {
yStep = 1;
}
lineThickness = 5 - Math.sqrt((x2 - x1) *(x2-x1) + (y2 - y1) * (y2-y1))/10;
if(lineThickness < 1){
lineThickness = 1;
}
for (var x = x1; x < x2; x++) {
if (steep) {
ctx.fillRect(y, x, lineThickness , lineThickness );
} else {
ctx.fillRect(x, y, lineThickness , lineThickness );
}
error += de;
if (error >= 0.5) {
y += yStep;
error -= 1.0;
}
}
lastX = mouseX;
lastY = mouseY;
}
});
$(canvas).mouseup(function(e)
{
painting = false;
});
$("#btnRotate").click(function()
{
rotate();
});
});
CSS
#main{outline: 1px solid orange; display: inline-block; position: relative;}
span{position: relative;}
https://jsfiddle.net/mgf8uz7s/