Flip images at 30 degrees?

匿名 (未验证) 提交于 2019-12-03 01:27:01

问题:

In canvas I know that I can flip images horizontally and vertically by doing this:

vc.scale(-1, -1) 

But is there some way to flip an image along a 30 degree symmetry line?

回答1:

Yes, you can accomplish this using the rotate() method of canvas :

var ctx = document.getElementById("myCanvas").getContext("2d"); var img = new Image(); img.src = "http://photos.the-scientist.com/articleImages/48000/48607-1-t.jpg"; img.onload = function() {     ctx.rotate(30 * Math.PI / 180);     ctx.translate(ctx.canvas.width / 2, ctx.canvas.height / 2);     ctx.scale(1, -1);     ctx.drawImage(img, -65, 65); }


回答2:

Rotate image 30 degrees, flip image, rotate -30 degrees.



回答3:

Mirror along line

You can mirror along any line using the following function. It sets the transform so that you can render your scene as normal and it will be mirrored along the line.

function mirrorTransformLine(line){     var x1 = line.x1;     var y1 = line.y1;     var x2 = line.x2;     var y2 = line.y2;     if(x1 > x2){  // to save some messing about with signs make the line always from left to right         x2 = line.x1;         y2 = line.y1;         x1 = line.x2;         y1 = line.y2;     }     var x = x2-x1;  // get the vector from line start to end     var y = y2-y1;      var ox = -x1;  // get vector from line start to origin     var oy = -y1;     var len = Math.hypot(x,y); // get the length of the line     var nx = x / len;  // normalise the line     var ny = y / len;       // We must find the mirrored origin     // get the unit distance along the line where the mirrored y axis intercepts     var u = (ox * x + oy * y)/(y * y + x * x);     var dx = u * len; // get the x dist of the mirrored origin         var dy = Math.hypot(x1 + x * u, y1 + y * u); // get the mirrored y axis distance from line      // the above code does not account for the direction of the origin. We don't know if its above or below the line     // we can get the cross product of the mirror line and the vector to the origin. This will give us the sign (direction) to the origin     dy *=  Math.sign(ox * y - oy * x); // flip the y distance if needed     // calculate the  the location of the mirrored origin     var mox = dx * nx - dy * ny + x1;     var moy = dx * ny + dy * nx + y1;       // Find the angle of the line to the x axis     // var cross = 1 * ny - 0 * nx; // cross product give the sin of the angle between the line and the x axis     // As the cross product is with 1,0 we can simplify     var ang = Math.asin(ny); // with ny the cross product      // now find the mirrored angle which is 2 times the angle to the x axis     // use that angle to get the new x axis     var axx = Math.cos(ang*2);     var axy = Math.sin(ang*2);      // this represents the x axis of the transform     // you would normally rotate it clockwise 90 for the y axis      // to mirror its anticlockwise     ctx.setTransform(axx,axy,axy,-axx,mox,moy); } 

Thus if you have a line at 30 deg

var line = {      x1 : 100,      y1 : 100,      x2 : 100 + Math.cos((1/6)* Math.PI), // (1/6) *PI is 30 deg      y2 : 100 + Math.sin((1/6)* Math.PI), }  // draw the scene ctx.fillRect(50,50,50,100); mirrorTransformLine(line); // create the mirror transformation ctx.fillRect(50,50,50,100); // draw the scene again this time its is mirrored ctx.setTransform(1,0,0,1,0,0); // restore the transform to default 

As a demo.

Use mouse to drag ends of red line to see it create the mirror transform. The scene is draw twice using the same coordinates. I have also clipped to the line so that the mirror does not overlap.

function mirrorTransformLine(line){     var x1 = line.x1;     var y1 = line.y1;     var x2 = line.x2;     var y2 = line.y2;     if(x1 > x2){  // to save some messing about with signs make the line always from left to right         x2 = line.x1;         y2 = line.y1;         x1 = line.x2;         y1 = line.y2;     }     var x = x2-x1;  // get the vector from line start to end     var y = y2-y1;      var ox = -x1;  // get vector from line start to origin     var oy = -y1;     var len = Math.hypot(x,y); // get the length of the line     var nx = x / len;  // normalise the line     var ny = y / len;       // We must find the mirrored origin     // get the unit distance along the line where the mirrored y axis intercepts     var u = (ox * x + oy * y)/(y * y + x * x);     var dx = u * len; // get the x dist of the mirrored origin         var dy = Math.hypot(x1 + x * u, y1 + y * u); // get the mirrored y axis distance from line      // the above code does not acount for the direction of the origin. We dont know if its above or below the line     // we can get the cross product of the mirror line and the vector to the origin. This will give us the sign (direction) to the origin     dy *=  Math.sign(ox * y - oy * x);     // calculate the  the location of the mirrored origin     var mox = dx * nx - dy * ny + x1;     var moy = dx * ny + dy * nx + y1;           // Find the angle of the line to the x axis     // var cross = 1 * ny - 0 * nx; // cross product give the sin of the angle between the line and the x axis     // As the cross product is with 1,0 we can simplify     var ang = Math.asin(ny); // with ny the cross product          // now find the mirrored angle which is 2 time the angle to the x axis     // use that angle to get the new x axis     var axx = Math.cos(ang*2);     var axy = Math.sin(ang*2);          // this represents the x axis of the transform     // you would normally rotate it clockwise 90 for the y axis      // to mirror its anticlockwise     ctx.setTransform(axx,axy,axy,-axx,mox,moy); }   function clipToLine(line){     var x =line.x2-line.x1;  // get the vector from line start to end     var y =line.y2-line.y1;       var len = Math.hypot(x,y); // get the length of the line     var nx = x / len;  // normalise the line     var ny = y / len;     // from 1000 px before start to 1000 px after end create dividing line     ctx.beginPath();     ctx.moveTo(line.x1 - nx * 1000, line.y1 - ny * 1000);     ctx.lineTo(line.x2 + nx * 1000, line.y2 + ny * 1000);     ctx.lineTo(line.x2 + nx * 1000 - ny * 1000, line.y2 + ny * 1000 + nx * 1000);     ctx.lineTo(line.x1 - nx * 1000 - ny * 1000, line.y1 - ny * 1000 + nx * 1000);     ctx.clip();           }  var line; var onResize = function(){  // this is called at start     line = {         x1 : 10,          y1 : canvas.height /2,         x2 : canvas.width -10,         y2 : canvas.height /2,     };     ctx.font = Math.floor(canvas.height /10) + "px arial";     ctx.textAlign = "center";     ctx.textBaseline = "middle"; } function drawLine(line,sCol,width){     ctx.strokeStyle = sCol;     ctx.lineWidth = width;     ctx.beginPath();     ctx.moveTo(line.x1,line.y1);     ctx.lineTo(line.x2,line.y2);     ctx.stroke(); } function drawCircle(x,y,r,fCol,sCol,width){     ctx.fillStyle = fCol;     ctx.strokeStyle = sCol;     ctx.lineWidth = width;     ctx.beginPath();     ctx.arc(x,y,r,0,Math.PI*2);     if(fCol) {ctx.fill()}     if(sCol) {ctx.stroke()}      } var dragging = 0; function display() {      ctx.setTransform(1, 0, 0, 1, 0, 0); // reset transform     ctx.globalAlpha = 1; // reset alpha     ctx.clearRect(0, 0, w, h);     var dist = Math.hypot(line.x1 - mouse.x, line.y1 - mouse.y);     var dist1 = Math.hypot(line.x2 - mouse.x, line.y2 - mouse.y);     var col1 = "blue";     var col2 = "blue";     if(dragging){         if(dragging === 1){             line.x1 = mouse.x;             line.y1 = mouse.y;             canvas.style.cursor = "move";         }else{             line.x2 = mouse.x;             line.y2 = mouse.y;             canvas.style.cursor = "move";         }         if(mouse.buttonRaw !== 1){             dragging = 0;             canvas.style.cursor = "default";         }     }else if(dist1  c(e));             }             e.preventDefault();         }         m.addCallback = function (callback) {             if (typeof callback === "function") {                 if (m.callbacks === undefined) {                     m.callbacks = [callback];                 } else {                     m.callbacks.push(callback);                 }             }         }         m.start = function (element) {             if (m.element !== undefined) {                 m.removeMouse();             }             m.element = element === undefined ? document : element;             m.mouseEvents.forEach(n => {                 m.element.addEventListener(n, mouseMove);             });             m.element.addEventListener("contextmenu", preventDefault, false);             m.active = true;         }         m.remove = function () {             if (m.element !== undefined) {                 m.mouseEvents.forEach(n => {                     m.element.removeEventListener(n, mouseMove);                 });                 m.element.removeEventListener("contextmenu", preventDefault);                 m.element = m.callbacks = undefined;                 m.active = false;             }         }         return mouse;     })();        function update(timer) { // Main update loop         if(ctx === undefined){             return;         }         globalTime = timer;         display(); // call demo code         requestAnimationFrame(update);     }     setTimeout(function(){         resizeCanvas();         mouse.start(canvas, true);         window.addEventListener("resize", resizeCanvas);         requestAnimationFrame(update);     },0); })(); /** SimpleFullCanvasMouse.js end **/


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!