在画布中我知道我可以通过这样做水平和垂直翻转图像:
String valueUrlEncoded = URLEncoder.encode(value, "UTF-8")
但有没有办法沿30度对称线翻转图像?
答案 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
作为演示。
使用鼠标拖动红线的末端以查看它创建镜像变换。场景使用相同的坐标绘制两次。我也剪了一条线,这样镜子就不会重叠了。
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;