翻转图像30度?

时间:2017-02-28 12:09:43

标签: html dom canvas

在画布中我知道我可以通过这样做水平和垂直翻转图像:

String valueUrlEncoded = URLEncoder.encode(value, "UTF-8")

但有没有办法沿30度对称线翻转图像?

3 个答案:

答案 0 :(得分:1)

将图像旋转30度,翻转图像,旋转-30度。

答案 1 :(得分:1)

是的,您可以使用canvas的rotate()方法完成此操作:

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);
}
<canvas id="myCanvas" width="300" height="300">

答案 2 :(得分:0)

沿线镜像

您可以使用以下功能沿任意线镜像。它设置变换,以便您可以正常渲染场景,并沿着线条镜像。

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);
}

因此,如果你有一个30度的线

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

作为演示。

使用鼠标拖动红线的末端以查看它创建镜像变换。场景使用相同的坐标绘制两次。我也剪了一条线,这样镜子就不会重叠了。

&#13;
&#13;
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 < dist && dist1 < 40){
        col2 = "red";
        canvas.style.cursor = "move";
        if(mouse.buttonRaw === 1){
            dragging = 2;
        }
    }else
    if(dist < dist1 && dist < 40){
        col1 = "red"
        canvas.style.cursor = "move";
        if(mouse.buttonRaw === 1){
            dragging = 1;
        }
    }else{
        canvas.style.cursor = "default";
        
    }
    ctx.save();
    clipToLine(line);
    drawCircle(canvas.width /2, canvas.height / 4 , canvas.height / 5, "Green","Blue",10);
    drawCircle(canvas.width /2, canvas.height * (3/4) , canvas.height / 5, "Blue","Green",10);
    ctx.fillStyle = "black";
    ctx.fillText("Mirror about the line.",canvas.width / 2, canvas.height / 2);
    ctx.restore();
    mirrorTransformLine(line);
    ctx.save();
    clipToLine(line);
    drawCircle(canvas.width /2, canvas.height / 4 , canvas.height / 5, "Green","Blue",10);
    drawCircle(canvas.width /2, canvas.height * (3/4) , canvas.height / 5, "Blue","Green",10);
    ctx.fillStyle = "#444";
    ctx.fillText("Mirror about the line.",canvas.width / 2, canvas.height / 2);
    ctx.restore();

    drawLine(line,"red",4);
    drawCircle(line.x1,line.y1,10,"white",col1,4);
    drawCircle(line.x2,line.y2,10,"white",col2,4);

}









//===========================================================================
// Boilerplat code from here down not part of answer
var w, h, cw, ch, canvas, ctx, mouse, globalTime = 0, firstRun = true;



;(function(){
    const RESIZE_DEBOUNCE_TIME = 100;
    var  createCanvas, resizeCanvas, setGlobals, resizeCount = 0;
    createCanvas = function () {
        var c,
        cs;
        cs = (c = document.createElement("canvas")).style;
        cs.position = "absolute";
        cs.top = cs.left = "0px";
        cs.zIndex = 1000;
        document.body.appendChild(c);
        return c;
    }
    resizeCanvas = function () {
        if (canvas === undefined) {
            canvas = createCanvas();
        }
        canvas.width = innerWidth;
        canvas.height = innerHeight;
        ctx = canvas.getContext("2d");
        if (typeof setGlobals === "function") {
            setGlobals();
        }
        if (typeof onResize === "function") {
            if(firstRun){
                onResize();
                firstRun = false;
            }else{
                resizeCount += 1;
                setTimeout(debounceResize, RESIZE_DEBOUNCE_TIME);
            }
        }
    }
    function debounceResize() {
        resizeCount -= 1;
        if (resizeCount <= 0) {
            onResize();
        }
    }
    setGlobals = function () {
        cw = (w = canvas.width) / 2;
        ch = (h = canvas.height) / 2;
    }
    mouse = (function () {
        function preventDefault(e) {
            e.preventDefault();
        }
        var mouse = {
            x : 0,
            y : 0,
            w : 0,
            alt : false,
            shift : false,
            ctrl : false,
            buttonRaw : 0,
            over : false,
            bm : [1, 2, 4, 6, 5, 3],
            active : false,
            bounds : null,
            crashRecover : null,
            mouseEvents : "mousemove,mousedown,mouseup,mouseout,mouseover,mousewheel,DOMMouseScroll".split(",")
        };
        var m = mouse;
        function mouseMove(e) {
            var t = e.type;
            m.bounds = m.element.getBoundingClientRect();
            m.x = e.pageX - m.bounds.left;
            m.y = e.pageY - m.bounds.top;
            m.alt = e.altKey;
            m.shift = e.shiftKey;
            m.ctrl = e.ctrlKey;
            if (t === "mousedown") {
                m.buttonRaw |= m.bm[e.which - 1];
            } else if (t === "mouseup") {
                m.buttonRaw &= m.bm[e.which + 2];
            } else if (t === "mouseout") {
                m.buttonRaw = 0;
                m.over = false;
            } else if (t === "mouseover") {
                m.over = true;
            } else if (t === "mousewheel") {
                m.w = e.wheelDelta;
            } else if (t === "DOMMouseScroll") {
                m.w = -e.detail;
            }
            if (m.callbacks) {
                m.callbacks.forEach(c => 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 **/
&#13;
&#13;
&#13;