camanjs and rotate plugin not working properly - javascript

Has anyone made rotate plugin work nice with camanjs? I have compiled camanjs using cofee and included the extra plugins. One of them is rotate. The rotate plugin is the following
Caman.Plugin.register("rotate", function(degrees) {
var angle, canvas, ctx, height, to_radians, width, x, y;
angle = degrees % 360;
if (angle === 0) {
return this.dimensions = {
width: this.canvas.width,
height: this.canvas.height
};
}
to_radians = Math.PI / 180;
if (typeof exports !== "undefined" && exports !== null) {
canvas = new Canvas();
} else {
canvas = document.createElement('canvas');
Util.copyAttributes(this.canvas, canvas);
}
if (angle === 90 || angle === -270 || angle === 270 || angle === -90) {
width = this.canvas.height;
height = this.canvas.width;
x = width / 2;
y = height / 2;
} else if (angle === 180) {
width = this.canvas.width;
height = this.canvas.height;
x = width / 2;
y = height / 2;
} else {
width = Math.sqrt(Math.pow(this.originalWidth, 2) + Math.pow(this.originalHeight, 2));
height = width;
x = this.canvas.height / 2;
y = this.canvas.width / 2;
}
canvas.width = width;
canvas.height = height;
ctx = canvas.getContext('2d');
ctx.save();
ctx.translate(x, y);
ctx.rotate(angle * to_radians);
ctx.drawImage(this.canvas, -this.canvas.width / 2, -this.canvas.height / 2, this.canvas.width, this.canvas.height);
ctx.restore();
return this.replaceCanvas(canvas);
});
plus
Caman.Filter.register("rotate", function() {
return this.processPlugin("rotate", Array.prototype.slice.call(arguments, 0));
});
html
<img id="myimage" src="image.src">
javascript
caman = Caman("#myimage");
caman.rotate(45);
caman.render();
But when rotating with degrees other than 90, 270 -90 or 180 -180 the result is not wanted because image gets "eaten" on the edges
Funny thing is that when hitting revert (lets say i want to change the brightness of the rotated image more than one times) then the original image appears on the canvas but distorted
And a third problems is that if you rotate the image 90 degrees everything works great the image rotates and stays where it was (on the left). But if you do 45 degrees rotation the canvas does not re-adjust as size and the image stays in the middle. Can this be fixxed? Has anyone make it work correctly? Would you suggest another library maybe? I need the rotation functionality.

Caman.Plugin.register("rotate", function(degrees) {
// add this 3 lint at last into the function.
this.angle += degrees;
this.rotated = true;
return this.replaceCanvas(canvas);
}
Caman.prototype.originalVisiblePixels = function () {
var canvas, coord, ctx, endX, endY, i, imageData, pixel, pixelData, pixels, scaledCanvas, startX, startY, width, _i, _j, _len, _ref, _ref1, _ref2, _ref3;
if (!Caman.allowRevert) {
throw "Revert disabled";
}
pixels = [];
startX = this.cropCoordinates.x;
endX = startX + this.width;
startY = this.cropCoordinates.y;
endY = startY + this.height;
if (this.resized) {
canvas = document.createElement('canvas');
canvas.width = this.originalWidth;
canvas.height = this.originalHeight;
ctx = canvas.getContext('2d');
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
pixelData = imageData.data;
_ref = this.originalPixelData;
for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
pixel = _ref[i];
pixelData[i] = pixel;
}
ctx.putImageData(imageData, 0, 0);
scaledCanvas = document.createElement('canvas');
scaledCanvas.width = this.width;
scaledCanvas.height = this.height;
ctx = scaledCanvas.getContext('2d');
ctx.drawImage(canvas, 0, 0, this.originalWidth, this.originalHeight, 0, 0, this.width, this.height);
pixelData = ctx.getImageData(0, 0, this.width, this.height).data;
width = this.width;
}
else if (this.rotated) {
canvas = document.createElement('canvas');//Canvas for initial state
canvas.width = this.originalWidth; //give it the original width
canvas.height = this.originalHeight; //and original height
ctx = canvas.getContext('2d');
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
pixelData = imageData.data;//get the pixelData (length equal to those of initial canvas
_ref = this.originalPixelData; //use it as a reference array
for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
pixel = _ref[i];
pixelData[i] = pixel; //give pixelData the initial pixels
}
ctx.putImageData(imageData, 0, 0); //put it back on our canvas
rotatedCanvas = document.createElement('canvas'); //canvas to rotate from initial
rotatedCtx = rotatedCanvas.getContext('2d');
rotatedCanvas.width = this.canvas.width;//Our canvas was already rotated so it has been replaced. Caman's canvas attribute is allready rotated, So use that width
rotatedCanvas.height = this.canvas.height; //the same
x = rotatedCanvas.width / 2; //for translating
y = rotatedCanvas.width / 2; //same
rotatedCtx.save();
rotatedCtx.translate(x, y);
rotatedCtx.rotate(this.angle * Math.PI / 180); //rotation based on the total angle
rotatedCtx.drawImage(canvas, -canvas.width / 2, -canvas.height / 2, canvas.width, canvas.height); //put the image back on canvas
rotatedCtx.restore(); //restore it
pixelData = rotatedCtx.getImageData(0, 0, rotatedCanvas.width, rotatedCanvas.height).data; //get the pixelData back
width = rotatedCanvas.width; //used for returning the pixels in revert function
} else {
pixelData = this.originalPixelData;
width = this.originalWidth;
}
for (i = _j = 0, _ref1 = pixelData.length; _j < _ref1; i = _j += 4) {
coord = Pixel.locationToCoordinates(i, width);
if (((startX <= (_ref2 = coord.x) && _ref2 < endX)) && ((startY <= (_ref3 = coord.y) && _ref3 < endY))) {
pixels.push(pixelData[i], pixelData[i + 1], pixelData[i + 2], pixelData[i + 3]);
}
}
return pixels;
};
Caman.prototype.reset = function() {
//....
this.angle = 0;
this.rotated = false;
}

Related

Double image background on canvas not sharing the same size

I'm trying to make a section on a website have two background images that will reveal the bottom one as the pointer moves across the screen.
I'm still new to javascript, and my code is made up of bits and pieces that I've found on google, but I can't seem to get the top image to share the same resolution and image size for whatever reason as the bottom image.
Here is the link to my codepen: https://codepen.io/Awktopus/pen/zYwKOKO
And here is my code:
HTML:
<canvas id="main-canvas" id="canvas-size" class="background-size"></canvas>
<image src="https://i.imgur.com/PbGAAIy.jpg" id="upper-image" class="hidden-bg"></img>
<image src="https://i.imgur.com/Gx14sKW.jpg" id="lower-image" class="hidden-bg"></img>
CSS:
.hidden-bg {
display: none;
}
JS:
var can = document.getElementById('main-canvas');
var ctx = can.getContext('2d');
can.width = window.innerWidth;
can.height = window.innerWidth / 2;
var upperImg = document.getElementById("upper-image");
var lowerImg = document.getElementById("lower-image");
var pat = ctx.createPattern(upperImg, "no-repeat");
var canvas = ctx.canvas ;
var hRatio = canvas.width / lowerImg.width ;
var vRatio = canvas.height / lowerImg.height ;
var ratio = Math.max ( hRatio, vRatio );
var centerShift_x = ( canvas.width - lowerImg.width*ratio ) / 2;
var centerShift_y = ( canvas.height - lowerImg.height*ratio ) / 2;
can.addEventListener('mousemove', function(e) {
var mouse = getMouse(e, can);
redraw(mouse);
}, false);
function redraw(mouse) {
can.width = can.width;
ctx.clearRect(0,0,canvas.width, canvas.height);
ctx.drawImage(lowerImg, 0,0, lowerImg.width, lowerImg.height, centerShift_x,centerShift_y,lowerImg.width*ratio, lowerImg.height*ratio);
ctx.beginPath();
ctx.rect(0,0,can.width,can.height);
ctx.arc(mouse.x, mouse.y, 250, 0, Math.PI*2, true)
ctx.clip();
ctx.fillStyle = pat;
ctx.fillRect(0, 0, lowerImg.width, lowerImg.height, centerShift_x, centerShift_y, lowerImg.width*ratio, lowerImg.height*ratio);
}
var img = new Image();
img.onload = function() {
redraw({x: -500, y:-500})
}
function getMouse(e, canvas) {
var element = canvas,
offsetX = 0,
offsetY = 0,
mx, my;
if (element.offsetParent !== undefined) {
do {
offsetX += element.offsetLeft;
offsetY += element.offsetTop;
} while ((element = element.offsetParent));
}
mx = e.pageX - offsetX;
my = e.pageY - offsetY;
return {
x: mx,
y: my
};
}
If I understood this right you will want to set the width and height and draw the upper image using drawImage(). Just use the same ratios as the lowerImage. No need to use createPattern for this.
codepen: https://codepen.io/jfirestorm44/pen/BaRLoxX
var can = document.getElementById('main-canvas');
var ctx = can.getContext('2d');
can.width = window.innerWidth;
can.height = window.innerWidth / 2;
var upperImg = document.getElementById("upper-image");
var lowerImg = document.getElementById("lower-image");
//var pat = ctx.createPattern(upperImg, "no-repeat");
var canvas = ctx.canvas ;
var hRatio = canvas.width / lowerImg.width ;
var vRatio = canvas.height / lowerImg.height ;
var ratio = Math.max ( hRatio, vRatio );
var centerShift_x = ( canvas.width - lowerImg.width*ratio ) / 2;
var centerShift_y = ( canvas.height - lowerImg.height*ratio ) / 2;
can.addEventListener('mousemove', function(e) {
var mouse = getMouse(e, can);
redraw(mouse);
}, false);
function redraw(mouse) {
can.width = can.width;
ctx.clearRect(0,0,canvas.width, canvas.height);
ctx.drawImage(lowerImg, 0,0, lowerImg.width, lowerImg.height, centerShift_x,centerShift_y,lowerImg.width*ratio, lowerImg.height*ratio);
ctx.beginPath();
ctx.rect(0,0,can.width,can.height);
ctx.arc(mouse.x, mouse.y, 250, 0, Math.PI*2, true)
ctx.clip();
ctx.drawImage(upperImg, 0,0, lowerImg.width, lowerImg.height, centerShift_x,centerShift_y,lowerImg.width*ratio, lowerImg.height*ratio);
}
var img = new Image();
img.onload = function() {
redraw({x: -500, y:-500})
}
function getMouse(e, canvas) {
var element = canvas,
offsetX = 0,
offsetY = 0,
mx, my;
if (element.offsetParent !== undefined) {
do {
offsetX += element.offsetLeft;
offsetY += element.offsetTop;
} while ((element = element.offsetParent));
}
mx = e.pageX - offsetX;
my = e.pageY - offsetY;
return {
x: mx,
y: my
};
}
.hidden-bg {
display: none;
}
<canvas id="main-canvas" id="canvas-size" class="background-size"></canvas>
<image src="https://i.imgur.com/PbGAAIy.jpg" id="upper-image" class="hidden-bg"></img>
<image src="https://i.imgur.com/Gx14sKW.jpg" id="lower-image" class="hidden-bg"></img>

draw an arc with two different colors in javascript

I am working on a canvas. I want to draw an arc with a different two-color, like first half will be green second half will be red.
sample code
// CANVAS
const canvas = document.getElementById('bar'),
width = canvas.width,
height = canvas.height;
// CANVAS PROPERTIES
const ctx = canvas.getContext('2d');
ctx.lineWidth = 6;
ctx.strokeStyle = 'green';
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
const x = width / 2,
y = height / 2,
radius = 41,
circum = Math.PI * 2,
start = 2.37,
finish = 75;
let curr = 0;
const raf =
window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
window.requestAnimationFrame = raf;
function animate(draw_to) {
//ctx.clearRect(0, 0, width, height);
ctx.beginPath();
ctx.arc(x, y, radius, start, draw_to, false);
ctx.stroke();
curr++;
if (curr < finish + 1) {
requestAnimationFrame(function () {
animate(circum * curr / 100 + start);
});
}
}
animate();
code link https://jsfiddle.net/gowtham25/bp0myt21/11/
Something like this?
const canvas = document.querySelector('canvas')
const ctx = canvas.getContext('2d')
const x = canvas.width / 2
const y = canvas.height / 2
const radius = 41
const start = -25
const end = 75
const width = 6
function DrawArc(x, y, radius, start, end, width, color) {
ctx.beginPath()
ctx.lineWidth = width
ctx.strokeStyle = color
ctx.arc(x, y, radius, start, end, false)
ctx.stroke()
}
function DrawGauge(percentage) {
const rotation = Math.PI * 0.75
const angle = Math.PI * 1.5
const current = angle * percentage / 100
DrawArc(x, y, radius, rotation, rotation + current, width, 'green')
DrawArc(x, y, radius, rotation + current, rotation + angle, width, 'red')
}
function Animate(percent = 0) {
if (percent < 0) return
if (percent > 100) return
DrawGauge(percent)
requestAnimationFrame(() => Animate(++percent))
}
Animate()
<canvas></canvas>
I recommend breaking down the things you want to draw into functions at the very least so you can easily draw the item by passing in the parameters each time and can reuse the function to draw multiple different versions of that item.
Personally I'd create a class for the arc drawing and a class for the gauge drawing and then the gauge would draw two arcs based on the value of its percentage property. That way the drawing is separated from your data logic which is extremely important as you start doing more complex things with more draw calls.
You need to change the startAngle parameter in
ctx.arc(x, y, radius, startAngle, endAngle [, anticlockwise]);
Currently, if you modify the strokeStyle without changing the startAngle it will just draw on the same path.
https://jsfiddle.net/97ogkwas/4/
// CANVAS
const canvas = document.getElementById('bar'),
width = canvas.width,
height = canvas.height;
// CANVAS PROPERTIES
const ctx = canvas.getContext('2d');
ctx.lineWidth = 6;
ctx.strokeStyle = 'green';
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
let x = width / 2,
y = height / 2,
radius = 41,
circum = Math.PI * 2
start = 0.5* Math.PI
finish = 75;
let curr = 0;
const raf =
window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
window.requestAnimationFrame = raf;
function animate(draw_to) {
//ctx.clearRect(0, 0, width, height);
ctx.beginPath();
if(curr>45){
ctx.strokeStyle = 'red';
start = 1* Math.PI;
}
ctx.arc(x, y, radius, start, draw_to, false);
ctx.stroke();
curr++;
if (curr < finish + 1) {
requestAnimationFrame(function () {
animate(circum * curr / 100 + start);
});
}
}
animate();
#bar {
position: absolute;
top: 0;
left: 0;
}
<canvas id="bar" width="100" height="100"></canvas>
https://jsfiddle.net/97ogkwas/4/
// CANVAS
const canvas = document.getElementById('bar'),
width = canvas.width,
height = canvas.height;
// CANVAS PROPERTIES
const ctx = canvas.getContext('2d');
ctx.lineWidth = 1;
ctx.strokeStyle = 'green';
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
// CANVAS PROPERTIES
const ctx2 = canvas.getContext('2d');
ctx2.lineWidth = 1;
ctx2.shadowOffsetX = 0;
ctx2.shadowOffsetY = 0;
var x = width / 2,
y = height / 2,
radius = 40,
circum = Math.PI * 2,
start = 2.37,
finish = 50;
let curr = 0;
const raf = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
window.requestAnimationFrame = raf;
function animate(draw_to) {
//ctx.clearRect(0, 0, width, height);
ctx.beginPath();
ctx.arc(x, y, radius, start, draw_to, false);
ctx.stroke();
curr++;
if (curr < finish + 5) {
requestAnimationFrame(function () {
animate(circum * curr / 100 + start);
});
}
}
function animate2(draw_to) {
//ctx.clearRect(0, 0, width, height);
ctx2.beginPath();
ctx2.arc(x, y, radius, start, draw_to, false);
ctx2.stroke();
curr++;
if (curr < finish + 5) {
requestAnimationFrame(function () {
animate2(circum * curr / 100 + start);
});
}
}
animate();
setTimeout(function(){
finish = 52;
start = 5.5;
ctx2.strokeStyle = 'red';
animate2();
}, 2000);
#bar {
position: absolute;
top: 0;
left: 0;
}
<canvas id="bar" width="100" height="100"></canvas>
The question is not clear at all! I am not sure but maybe someting like this:
https://jsfiddle.net/15srnh4w/

How to draw canvas trailing line with opacity

I'm attempting to draw the rotating line in this canvas animation with trailing opacity but it's not working. I've seen this effect with rectangles and arcs but never with a line, so I'm not sure what I need to add.
function radians(degrees) {
return degrees * (Math.PI / 180);
}
var timer = 0;
function sonar() {
var canvas = document.getElementById('sonar');
if (canvas) {
var ctx = canvas.getContext('2d');
var cx = innerWidth / 2,
cy = innerHeight / 2;
canvas.width = innerWidth;
canvas.height = innerHeight;
//ctx.clearRect(0, 0, innerWidth, innerHeight);
ctx.fillStyle = 'rgba(255, 255, 255, 0.5)';
ctx.fillRect(0, 0, innerWidth, innerHeight);
var radii = [cy, cy - 30, innerHeight / 3.33, innerHeight / 6.67];
for (var a = 0; a < 4; a++) {
ctx.beginPath();
ctx.arc(cx, cy, radii[a], radians(0), radians(360), false);
ctx.strokeStyle = 'limegreen';
ctx.stroke();
ctx.closePath();
}
// draw grid lines
for (var i = 0; i < 12; i++) {
var x = cx + cy * Math.cos(radians(i * 30));
var y = cy + cy * Math.sin(radians(i * 30));
ctx.beginPath();
ctx.moveTo(cx, cy);
ctx.lineTo(x, y);
ctx.lineCap = 'round';
ctx.strokeStyle = 'rgba(50, 205, 50, 0.45)';
ctx.stroke();
ctx.closePath();
}
if (timer <= 360) {
timer++;
ctx.beginPath();
ctx.fillstyle = 'limegreen';
ctx.moveTo(cx, cy);
ctx.lineTo(cx + cy * Math.cos(radians(timer)), cy + cy * Math.sin(radians(timer)));
ctx.strokeStyle = 'limegreen';
ctx.stroke();
ctx.closePath();
} else {
timer = 0;
}
requestAnimationFrame(sonar);
}
}
sonar();
jsbin example
Here are two ways to do this: with a gradient and by adding translucent lines.
Sidenote, you should try and only redraw what you need to redraw. I separated the canvases and put one on top of the other so that we don't redraw the grid all the time.
function radians(degrees) {
return degrees * (Math.PI / 180);
}
var timer = 0;
function trail() {
var canvas = document.getElementById('trail');
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, innerWidth, innerHeight);
var cx = innerWidth / 2,
cy = innerHeight / 2;
canvas.width = innerWidth;
canvas.height = innerHeight;
if (timer <= 360) {
timer++;
ctx.beginPath();
ctx.fillstyle = 'limegreen';
ctx.moveTo(cx, cy);
ctx.arc(cx,cy,cy,radians(timer-30),radians(timer));
ctx.lineTo(cx + cy * Math.cos(radians(timer)), cy + cy * Math.sin(radians(timer)));
var gradient = ctx.createLinearGradient(
cx+cy*Math.cos(radians(timer)), cy+cy*Math.sin(radians(timer)),
cx+cy*0.9*Math.cos(radians(timer-30)), cy+cy*0.9*Math.sin(radians(timer-30)));
gradient.addColorStop(0,'limegreen');
gradient.addColorStop(1,'transparent');
ctx.strokeStyle='transparent';
ctx.fillStyle = gradient;
ctx.fill();
ctx.beginPath();
var fade = 10;
for(var i =0;i<fade;i++)
{
ctx.moveTo(cx, cy);
ctx.lineTo(cx+cy*Math.cos(radians(180+timer-i*1.3)),cy+cy*Math.sin(radians(180+timer-i*1.3)));
ctx.strokeStyle ="rgba(50,205,50,0.1)";
ctx.lineWidth=5;
ctx.closePath();
ctx.stroke();
}
} else {
timer = 0;
}
requestAnimationFrame(trail);
}
function sonar() {
var canvas = document.getElementById('sonar');
if (canvas) {
var ctx = canvas.getContext('2d');
var cx = innerWidth / 2,
cy = innerHeight / 2;
canvas.width = innerWidth;
canvas.height = innerHeight;
//ctx.clearRect(0, 0, innerWidth, innerHeight);
var radii = [cy, cy - 30, innerHeight / 3.33, innerHeight / 6.67];
for (var a = 0; a < 4; a++) {
ctx.beginPath();
ctx.arc(cx, cy, radii[a], radians(0), radians(360), false);
ctx.strokeStyle = 'limegreen';
ctx.stroke();
ctx.closePath();
}
// draw grid lines
for (var i = 0; i < 12; i++) {
var x = cx + cy * Math.cos(radians(i * 30));
var y = cy + cy * Math.sin(radians(i * 30));
ctx.beginPath();
ctx.moveTo(cx, cy);
ctx.lineTo(x, y);
ctx.lineCap = 'round';
ctx.strokeStyle = 'rgba(50, 205, 50, 0.45)';
ctx.stroke();
ctx.closePath();
}
}
}
sonar();
trail();
canvas{
position: absolute;
}
<canvas id=sonar></canvas>
<canvas id=trail></canvas>
The problem is that to get this effect, you need to draw a triangle with a gradient along an arc, and you can't do that in a canvas. Gradients must be linear or radial.
The other option is to have an inner loop run each time you want to draw the sweeper, and go backwards from your sweeper line, drawing with slightly less opacity each time. But lets say you want your sweep to cover 15 degrees--obviously, if you have a 100% opacity line at d and a 5% opacity line at d - 15, that doesn't do the trick. So start filling in more lines, and more lines...you will have to draw so many lines to make it seem filled your performance would probably suffer.
My suggestion--you shouldn't have to redraw that on every frame. I would just make a PNG that looks like you want it to, and then place it and just rotate it around the center on each frame. No need to redraw it all the time then. That will be much faster than drawing a bunch of lines.
Canvas stack trails.
Below is a quick demo of how to use a stack of canvases to create a trailing effect.
You have a normal on screen canvas (this FX will not effect it) and then a stack of canvases for the trail FX. Each frame you move to the next canvas in the stack, first slightly clearing it then drawing to it what you want to trail. Then you render that canvas and the one just above it to the canvas.
A point to keep in mind is that the trails can also have a hugh range of FX, like blurring (just render each frame stack on itself slightly offset each time you render to it), zoom in and out trails. Trails on top or trails under. You can change the trail distance and much more.
It is overkill but over kill is fun.
The slider above the demo controls the trail length. Also the code need babel because I dont have time to write it for ES5.
Top slider is trail amount.One under that is trail distance. Trail dist does not transition well. Sorry about that.
//==============================================================================
// helper function
function $(query,q1){
if(q1 !== undefined){
if(typeof query === "string"){
var e = document.createElement(query);
if(typeof q1 !== "string"){
for(var i in q1){
e[i] = q1[i];
}
}else{
e.id = q1;
}
return e;
}
return [...query.querySelectorAll(q1)];
}
return [...document.querySelectorAll(query)];
}
function $$(element,e1){
if(e1 !== undefined){
if(typeof element === "string"){
$(element)[0].appendChild(e1);
return e1;
}
element.appendChild(e1);
return e1;
}
document.body.appendChild(element);
return element;
}
function $E(element,types,listener){
if(typeof types === "string"){
types = types.split(",");
}
element = $(element)[0];
types.forEach(t=>{
element.addEventListener(t,listener)
});
return element;
}
function R(I){
if(I === undefined){
return Math.random();
}
return Math.floor(Math.random()*I);
}
//==============================================================================
//==============================================================================
// answer code
// canvas size
const size = 512;
const trailDist = 10; // There is this many canvases so be careful
var trailDistCurrent = 10; // distance between trails
var clearAll = false;
// create a range slider for trail fade
$$($("input",{type:"range",width : size, min:0, max:100, step:0.1, value:50, id:"trail-amount",title:"Trail amount"}));
$("#trail-amount")[0].style.width = size + "px";
$E("#trail-amount","change,mousemove",function(e){fadeAmount = Math.pow(this.value / 100,2);});
// create a range slider trail distance
$$($("input",{type:"range",width : size, min:2, max:trailDist , step:1, value:trailDist , id:"trail-dist",title:"Trail seperation"}));
$("#trail-dist")[0].style.width = size + "px";
$E("#trail-dist","change,mousemove", function(e){
if(this.value !== trailDistCurrent){
trailDistCurrent= this.value;
clearAll = true;
}
});
$$($("br","")) // put canvas under the slider
// Main canvas
var canvas;
$$(canvas = $("canvas",{width:size,height:size})); // Not jquery. Just creates a canvas
// and adds canvas to the document
var ctx = canvas.getContext("2d");
// Trailing canvas
var trailCanvases=[];
var i =0; // create trail canvas
while(i++ < trailDist){trailCanvases.push($("canvas",{width:size,height:size}));}
var ctxT = trailCanvases.map(c=>c.getContext("2d")); // get context
var topCanvas = 0;
var fadeAmount = 0.5;
// Draw a shape
function drawShape(ctx,shape){
ctx.lineWidth = shape.width;
ctx.lineJoin = "round";
ctx.strokeStyle = shape.color;
ctx.setTransform(shape.scale,0,0,shape.scale,shape.x,shape.y);
ctx.rotate(shape.rot);
ctx.beginPath();
var i = 0;
ctx.moveTo(shape.shape[i++],shape.shape[i++]);
while(i < shape.shape.length){
ctx.lineTo(shape.shape[i++],shape.shape[i++]);
}
ctx.stroke();
}
// Create some random shapes
var shapes = (function(){
function createRandomShape(){
var s = [];
var len = Math.floor(Math.random()*5 +4)*2;
while(len--){
s[s.length] = (R() + R()) * 20 * (R() < 0.5 ? -1 : 1);
}
return s;
}
var ss = [];
var i = 10;
while(i--){
ss[ss.length] = createRandomShape();
}
ss[ss.length] = [0,0,300,0]; // create single line
return ss;
})();
// Create some random poits to move the shapes
var points = (function(){
function point(){
return {
color : "hsl("+R(360)+",100%,50%)",
shape : shapes[R(shapes.length)],
width : R(4)+1,
x : R(size),
y : R(size),
scaleMax : R()*0.2 + 1,
scale : 1,
s : 0,
rot : R()*Math.PI * 2,
dr : R()*0.2 -0.1,
dx : R()*2 - 1,
dy : R()*2 - 1,
ds : R() *0.02 + 0.01,
}
}
var line = shapes.pop();
var ss = [];
var i = 5;
while(i--){
ss[ss.length] = point();
}
var s = ss.pop();
s.color = "#0F0";
s.x = s.y = size /2;
s.dx = s.dy = s.ds = 0;
s.scaleMax = 0.5;
s.dr = 0.02;
s.shape = line;
s.width = 6;
ss.push(s);
return ss;
})();
var frameCount = 0; // used to do increamental fades for long trails
function update(){
// to fix the trail distance problem when fade is low and distance high
if(clearAll){
ctxT.forEach(c=>{
c.setTransform(1,0,0,1,0,0);
c.clearRect(0,0,size,size);
});
clearAll = false;
}
frameCount += 1;
// get the next canvas that the shapes are drawn to.
topCanvas += 1;
topCanvas %= trailDistCurrent;
var ctxTop = ctxT[topCanvas];
// clear the main canvas
ctx.setTransform(1,0,0,1,0,0); // reset transforms
// Fade the trail canvas
ctxTop.setTransform(1,0,0,1,0,0);
ctx.clearRect(0,0,size,size); // clear main canvas
// slowly blendout trailing layer
if(fadeAmount < 0.1){ // fading much less than this leaves perminant trails
// so at low levels just reduce how often the fade is done
if(((Math.floor(frameCount/trailDistCurrent)+topCanvas) % Math.ceil(1 / (fadeAmount * 10))) === 0 ){
ctxTop.globalAlpha = 0.1;
ctxTop.globalCompositeOperation = "destination-out";
ctxTop.fillRect(0,0,size,size);
}
}else{
ctxTop.globalAlpha = fadeAmount;
ctxTop.globalCompositeOperation = "destination-out";
ctxTop.fillRect(0,0,size,size);
}
ctxTop.globalCompositeOperation = "source-over";
ctxTop.globalAlpha = 1;
// draw shapes
for(var i = 0; i < points.length; i ++){
var p = points[i];
p.x += p.dx; // move the point
p.y += p.dy;
p.rot += p.dr;
p.s += p.ds;
p.dr += Math.sin(p.s) * 0.001;
p.scale = Math.sin(p.s) * p.scaleMax+1;
p.x = ((p.x % size) + size) % size;
p.y = ((p.y % size) + size) % size;
drawShape(ctxTop,p); // draw trailing layer (middle)
}
// draw the trail the most distance from the current position
ctx.drawImage(trailCanvases[(topCanvas + 1)%trailDistCurrent],0,0);
// do it all again.
requestAnimationFrame(update);
}
update();

Export image from canvas in printing size (300 DPI)

I am trying to make a canvas application and i get success. I just stuck in print image that is output of canvas. Size of image is too small to print enough.
Following is flow of application:
Upload image and draw to the canvas.
Do some operations like zoom, move and rotating on split canvas.
I have successfully generated single images from those splits
And I have export base64 from canvas to printing process.
Problem is here when I export data from canvas it's small image, even if I do some Imagick stuff to resize image quality of final image is not near to print on poster.
JavaScript:
function draw() {
var Activecanvas = document.getElementsByClassName("cf-photoframe-active");
var canvas = Activecanvas[0];
var ctx = canvas.getContext('2d');
var ActiveCanvasId = canvas.getAttribute("id");
var img = canvasDetail[ActiveCanvasId].selectedImage;
var imageX = canvasDetail[ActiveCanvasId].imageX;
var imageY = canvasDetail[ActiveCanvasId].imageY;
var resize = resizeDetail[ActiveCanvasId].resize;
var rotate = rotateDetail[ActiveCanvasId].rotate;
//if(resize)
$j("#resize").slider({
value: resize,
min: -300,
max: 300,
step: 1,
});
$j("#rotat").slider({
value: rotate,
min: -180,
max: 180,
step: 1,
});
if (img != '') {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save();
var im_width = parseInt(img.width + $j("#resize").slider('value'));
var im_height = parseInt(img.height + $j("#resize").slider('value'));
var maxWidth = canvas.width; // Max width for the image
var maxHeight = canvas.height;
var iswidthMax = 0;
var imageOrgWidth = img.width;
var imageOrgHeight = img.height;
if (maxWidth < maxHeight) {
iswidthMax = 1;
} else if (maxWidth == maxHeight) {
iswidthMax = 2;
}
if (iswidthMax == 1) {
maxWidth = (maxHeight * imageOrgWidth) / imageOrgHeight;
} else if (iswidthMax == 0) {
maxHeight = (maxWidth * imageOrgHeight) / imageOrgWidth;
} else if (iswidthMax == 2) {
if (img.width > img.height) {
maxWidth = (maxHeight * imageOrgWidth) / imageOrgHeight;
} else {
maxHeight = (maxWidth * imageOrgHeight) / imageOrgWidth;
}
}
var resizeVal = $j("#resize").slider('value');
var nw = maxWidth + resizeVal;
var resizeValHeight = maxHeight * resizeVal / maxWidth;
var nh = maxHeight + resizeValHeight;
ctx.translate(imageX, imageY);
ctx.rotate(rotate * Math.PI / 180);
ctx.translate(-nw / 2, -nh / 2);
ctx.drawImage(img, 0, 0, nw, nh);
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.restore();
}
}
If you have smaller canvas elements for editing, then you will have to recombine the data from those smaller canvas elements into a canvas element which is the full size and output the data from that element.
For simplicity's sake, let's say that you have cut the image into four quadrants and drawn to four canvas elements canvas[0] - canvas[3] for editing. You would then need to recombine them into one larger canvas doing something like the following...
var imgData = [];
for (var i = 0; i < 4; i++) {
var tmpCtx = canvas[i].getContext('2d');
imgData[i] = tmpCtx.getImageData(0, 0, canvas[i].width, canvas[i].height);
}
var fullSizeCanvas = document.createElement('canvas');
fullSizeCanvas.width = img.width * 2;
fullSizeCanvas.height = img.height * 2;
var fullCtx = fullSizeCanvas.getContext('2d');
fullCtx.putImageData(imgData[0], 0, 0);
fullCtx.putImageData(imgData[1], img.width, 0);
fullCtx.putImageData(imgData[2], 0, img.height);
fullCtx.putImageData(imgData[3], img.width, img.height);
var data = fullSizeCanvas.toDataURL();

HTML Canvas, blurring drawn polygon

I made this (run snippet below)
var Canvas = document.getElementById('c');
var ctx = Canvas.getContext('2d');
var resize = function() {
Canvas.width = Canvas.clientWidth;
Canvas.height = Canvas.clientHeight;
};
window.addEventListener('resize', resize);
resize();
var elements = [];
var presets = {};
presets.shard = function (x, y, s, random, color) {
return {
x: x,
y: y,
draw: function(ctx, t) {
this.x += 0;
this.y += 0;
var posX = this.x + + Math.sin((50 + x + (t / 10)) / 100) * 5;
var posy = this.y + + Math.sin((55 + x + (t / 10)) / 100) * 7;
ctx.beginPath();
ctx.fillStyle = color;
ctx.moveTo(posX, posy);
ctx.lineTo(posX+random,posy+random);
ctx.lineTo(posX+random,posy+random);
ctx.lineTo(posX+0,posy+50);
ctx.closePath();
ctx.fill();
}
}
};
for(var x = 0; x < Canvas.width; x++) {
for(var y = 0; y < Canvas.height; y++) {
if(Math.round(Math.random() * 60000) == 1) {
var s = ((Math.random() * 5) + 1) / 10;
if(Math.round(Math.random()) == 1){
var random = Math.floor(Math.random() * 100) + 10;
var colorRanges = ['#8c8886', '#9c9995'];
var color = colorRanges[Math.floor(Math.random() * colorRanges.length)];
elements.push(presets.shard(x, y, s, random, color));
}
}
}
}
setInterval(function() {
ctx.clearRect(0, 0, Canvas.width, Canvas.height);
var time = new Date().getTime();
for (var e in elements)
elements[e].draw(ctx, time);
}, 10);
<canvas id="c" width="1000" height="1000"\>
I just need to add one feature to be able to use it on the site I'm building it for. Some of the floating shards need to be blurred to give a sense of depth.
Can Canvas do this, and if so, how?
context.filter = 'blur(10px)';
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/filter
I used this few months ago, maybe it could work for you as well :
var canvas = document.getElementById("heroCanvas");
var canvasContext = canvas.getContext("2d");
var canvasBackground = new Image();
canvasBackground.src = "image.jpg";
var drawBlur = function() {
// Store the width and height of the canvas for below
var w = canvas.width;
var h = canvas.height;
// This draws the image we just loaded to our canvas
canvasContext.drawImage(canvasBackground, 0, 0, w, h);
// This blurs the contents of the entire canvas
stackBlurCanvasRGBA("heroCanvas", 0, 0, w, h, 100);
}
canvasBackground.onload = function() {
drawBlur();
}
Here the source : http://zurb.com/playground/image-blur-texture

Categories