Canvas elements appear skewed in Webkit with context blender - html

EDIT: Below is the original post, but I have figured out the problem. It appears the problem was with using a decimal number as the Y coordinate (destY). I sorted this out by rounding:
var rand = {
destX: Math.round(Math.random()*main.canvas.width),
destY: Math.random()*main.canvas.height
}
I have included images to show the difference between Firefox and Chrome. As you can see the images I have blended onto the canvas are skewed. Has anyone experienced this before? Is it a problem with context blender, or Webkits canvas in general?
var main;
$(document).ready(function(){
var canvas = document.getElementById('canvas');
main = canvas.getContext('2d');
main.canvas.width = $(window).width();
main.canvas.height = $(window).height()/2;
});
$(window).load(function(){
var array = new Array();
$('img').each(function(){
var temp = document.createElement('canvas');
var ctx = temp.getContext('2d');
ctx.canvas.width = this.width;
ctx.canvas.height = this.height;
ctx.drawImage(this,0,0);
var rand = {
destX: Math.random()*main.canvas.width,
destY: Math.random()*main.canvas.height
}
ctx.blendOnto(main,'multiply',rand);
});
});

Related

Image not appearing in canvas

I'm trying to load an image on my HTML5 canvas. I'm following a tutorial and I've done everything precisely.
My console prints "image loaded", so I know that it has found the png file. However, nothing shows up on screen.
I have tried resizing the canvas, and trying to make the image appear on different coordinates, to no avail.
<body>
<canvas id="my_canvas"></canvas>
</body>
<script>
var canvas = null;
var context = null;
var basicImage = null;
var setup = function() {
// Set up canvas
canvas = document.getElementById("my_canvas");
context = canvas.getContext('2d'); // lets us modify canvas visuals later
canvas.width = window.innerWidth; // 1200
canvas.height = window.innerHeight; // 720
// Load an image
basicImage = new Image();
basicImage.src = "bb8.png";
basicImage.onload = onImageLoad();
}
var onImageLoad = function() {
console.log("image loaded");
context.drawImage(basicImage, 0, 0);
}
setup();
</script>
Rather than drawing the image on basicImage.onload, try it on window.onload
var setup = function() {
// Set up canvas
canvas = document.getElementById("my_canvas");
context = canvas.getContext('2d'); // lets us modify canvas visuals later
canvas.width = window.innerWidth; // 1200
canvas.height = window.innerHeight; // 720
// Load an image
basicImage = new Image();
basicImage.src = "bb8.png";
}
window.onload = function() {
console.log("image loaded");
context.drawImage(basicImage, 0, 0);
}
setup();

Reveal background image on mouse move over front image

I want to reveal the background image on mouse move on the front image. I have tried it using fabricjs but it seems the pattern image offset is updated on mouse up.
I have also tried it using the making the pixels transparent of image on mouse move but there are performance issue on slow devices. Can you suggest any better solution.
HTML
<canvas id="container"></canvas>
JS
var canvasWidth = window.innerWidth;
var canvasHeight = window.innerHeight;
var backgroundUrl = "http://www.keenthemes.com/preview/metronic/theme/assets/global/plugins/jcrop/demos/demo_files/image2.jpg";
var frontUrl = "http://tofurious.wpengine.netdna-cdn.com/images/textures/texture-8.jpg";
var canvas = new fabric.Canvas('container', {
width:canvasWidth,
height:canvasHeight,
isDrawingMode: true
});
fnDrawImage(backgroundUrl);
drawPattern()
function fnDrawImage(_url){
var Image = fabric.Image.fromURL(_url, function(oImg) {
oImg.width = canvasWidth;
oImg.height = canvasHeight;
oImg.selectable = false;
canvas.add(oImg);
});
}
function drawPattern(){
var img = new Image();
img.src = frontUrl;
img.onload = function(){
img.width = canvasWidth;
img.height = canvasHeight;
fnTexturePattern(img);
//fnStartFreeDrawing(img);
}
}
function fnTexturePattern(_img){
var texturePatternBrush = new fabric.PatternBrush(canvas);
texturePatternBrush.source = _img;
canvas.freeDrawingBrush = texturePatternBrush;
canvas.freeDrawingBrush.width = 30;
}
JSFiddle - http://jsfiddle.net/3qp5y9jb/

How to drag an image after drop onto HTML5 Canvas?

I've modified a page where I can drag and drop images onto a canvas. It does everything I want except for one. I've tried multiple methods (including scripts, e.g. Kinetic and Raphael, which I still think may be the route to go) but have dead ended:
Once the image is dropped, I can't drag it on the canvas to a new position.
function drag(e)
{
//store the position of the mouse relativly to the image position
e.dataTransfer.setData("mouse_position_x",e.clientX - e.target.offsetLeft );
e.dataTransfer.setData("mouse_position_y",e.clientY - e.target.offsetTop );
e.dataTransfer.setData("image_id",e.target.id);
}
function drop(e)
{
e.preventDefault();
var image = document.getElementById( e.dataTransfer.getData("image_id") );
var mouse_position_x = e.dataTransfer.getData("mouse_position_x");
var mouse_position_y = e.dataTransfer.getData("mouse_position_y");
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// the image is drawn on the canvas at the position of the mouse when we lifted the mouse button
ctx.drawImage( image , e.clientX - canvas.offsetLeft - mouse_position_x , e.clientY - canvas.offsetTop - mouse_position_y );
}
function convertCanvasToImage() {
var canvas = document.getElementById('canvas');
var image_src = canvas.toDataURL("image/png");
window.open(image_src);
}
Here is a JSFiddle that I used as my initial start point - http://fiddle.jshell.net/gael/GF96n/4/ (drag the JSFiddle logo onto the canvas and then try to move it). I've since added CSS, tabs, content, etc. to my almost working page. The function I don't want to lose is the ability to drag the single image multiple times (clone) onto the canvas.
Any ideas/examples/pointers on how to create this functionality?
You need to do a couple of changes to your code, instead of drawing the image immediately to the canvas, you need to keep track of all images dropped. imagesOnCanvas will be filled with all images dropped.
var imagesOnCanvas = [];
function drop(e)
{
e.preventDefault();
var image = document.getElementById( e.dataTransfer.getData("image_id") );
var mouse_position_x = e.dataTransfer.getData("mouse_position_x");
var mouse_position_y = e.dataTransfer.getData("mouse_position_y");
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
imagesOnCanvas.push({
context: ctx,
image: image,
x:e.clientX - canvas.offsetLeft - mouse_position_x,
y:e.clientY - canvas.offsetTop - mouse_position_y,
width: image.offsetWidth,
height: image.offsetHeight
});
}
You also need an animation loop, which will go through all images in imagesOnCanvas and draw them sequentially. requestAnimationFrame is used to achieve this.
function renderScene() {
requestAnimationFrame(renderScene);
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.clearRect(0,0,
canvas.width,
canvas.height
);
for(var x = 0,len = imagesOnCanvas.length; x < len; x++) {
var obj = imagesOnCanvas[x];
obj.context.drawImage(obj.image,obj.x,obj.y);
}
}
requestAnimationFrame(renderScene);
Next you will have to monitor mousedown events on canvas, and if the event occurs on an image the startMove action can be called
canvas.onmousedown = function(e) {
var downX = e.offsetX,downY = e.offsetY;
// scan images on canvas to determine if event hit an object
for(var x = 0,len = imagesOnCanvas.length; x < len; x++) {
var obj = imagesOnCanvas[x];
if(!isPointInRange(downX,downY,obj)) {
continue;
}
startMove(obj,downX,downY);
break;
}
}
The isPointInRange function returns true if the mouse event occurred on an image object
function isPointInRange(x,y,obj) {
return !(x < obj.x ||
x > obj.x + obj.width ||
y < obj.y ||
y > obj.y + obj.height);
}
Once 'move mode' is active, the x/y coordinates of the object are changed to reflect the new mouse position
function startMove(obj,downX,downY) {
var canvas = document.getElementById('canvas');
var origX = obj.x, origY = obj.y;
canvas.onmousemove = function(e) {
var moveX = e.offsetX, moveY = e.offsetY;
var diffX = moveX-downX, diffY = moveY-downY;
obj.x = origX+diffX;
obj.y = origY+diffY;
}
canvas.onmouseup = function() {
// stop moving
canvas.onmousemove = function(){};
}
}
Working example here:
http://jsfiddle.net/XU2a3/41/
I know it's been like 2 years, but I'll give it a try... In the answer provided by #lostsource, the dataTransfer object is not supported in Opera browser, and the jsfiddle is not working. I desperately need that answer, that's what I've been looking for, but it's not working!

How do i clear the canvas for another animation?

Was wondering if any of you could help me
I've got to create an advert and want to have text flying in from the right.
So far I've managed to do it, but cannot clear the canvas for reanimation.
Here's my code so far:
<canvas id="canvas" width="800" height="200">Your browser doesn't support the canvas. <br/> I appologise for any inconvenience.
</canvas>
<script type = "text/javascript">
//Set up the canvas
var the_canvas_element = document.getElementById("canvas");
var the_canvas = the_canvas_element.getContext("2d");
//Start Variables
var x = 800;
//Start animation timing
var int = setInterval(draw,10);
var ljmulogo = new Image ();
{
ljmulogo.src = 'C:\Users\Chad\Documents\My Web Sites\CWK 2\Part A\Images\ljmu_logo.png'
setInterval (draw,100)
}
function draw()
{
//Clear canvas
the_canvas.clearRect(0,0,800,200);
//Draw text
the_canvas.fillStyle = "#000000";
the_canvas.font = "24pt arial";
the_canvas.fillText("Welcome to:",x,30);
the_canvas.fillStyle = "#000000";
the_canvas.font = "bold 24pt arial";
the_canvas.fillText("Liverpool John Moores University",x,70);
the_canvas.fillStyle = "#000000";
the_canvas.font = "32pt arial";
the_canvas.fillText("Computer Forensics",x,150);
//Check if at the end
if (x<=20)
{
//End animation
int = clearInterval(int);
}
else
{
//bring text in further
x = x -2;
}
}
</script>
Thanks a lot for any help, much appreciated :)
I'm not sure what's going on here, it doesn't look valid:
var ljmulogo = new Image ();
{
ljmulogo.src = 'C:\Users\Chad\Documents\My Web Sites\CWK 2\Part A\Images\ljmu_logo.png'
setInterval (draw,100)
}
To create a new image, try this:
//This code outside the draw loop
var ljmulogo = new Image();
ljmulogo.src = 'ljmu_logo.png';
//This code inside the draw loop
ctx.drawImage(ljmulogo, 0, 0);
(and remove the setInterval (draw,100) as you already have a setInterval + that 100 value is pretty high).

Rotating full window canvas

I am doing simple (for now) application to draw on canvas.
I can draw simple shapes like putting dots, squares, lines, but when I try to rotate whole image - nothing happens. No errors, no rotation. Please advise where is problem.
Canvas is updated to window size by function onwindowresize:
function adaptSize() {
var canvas = document.getElementById('canvas');
// set size to window
canvas.setAttribute('width',window.innerWidth);
canvas.setAttribute('height',window.innerHeight);
var ctx = canvas.getContext("2d");
// set state size to window
ctx.width = window.innerWidth;
ctx.height = window.innerHeight;
drawSaved();
inform('Canvas re-drawed - window resized');
}
Each draw function saves itself inlocalstorage to re-draw, for example placing dot:
function placeDot(x,y){
if(document.getElementById('colors').hasAttribute('chosen')){ var color = document.getElementById('colors').getAttribute('chosen');}else{ var color = 'rgba(0,0,0,1)'; }
var canvas = document.getElementById("canvas");
if(canvas.getContext) {
var ctx = canvas.getContext("2d");
ctx.save();
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(x-2,y-2,5,0,Math.PI*2,true);
ctx.fill();
ctx.restore();
}
save("//Dot("+x+","+y+",5,'"+color+"')");
return false;
}
than re-draw function:
function drawSaved(){
var picture = localStorage.getItem("picture");
var drawstate =document.getElementById('drawstate');
console.log('picture:'+picture+'.');
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
if((picture=="")||(picture==null)){
picture = ""
localStorage.setItem("picture", picture);
drawstate.innerHTML='picture empty';
ctx.clearRect(0, 0, window.innerWidth, window.innerHeight);
console.log('cleared');
}else{
console.log(picture);
saved = picture.split('//');
for(var i=1;i<saved.length;i++){
eval(saved[i]);
}
drawstate.innerHTML='picture restored';
}
}
So, creating rotation:
function turn(angle){
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.save();
console.log('saved');
ctx.rotate(angle);
console.log('rotated by'+angle);
ctx.restore();
console.log('restored');
save("//Turn('"+angle+"')");
return false;
}
All this gives no effect on rotation - or any other transformation. Drawing is OK.
Please help.
Thanks
Pifon
PS: this programme is: http://www.pifon.com/3d/ rotation should work on arrow right press.
Full script: http://www.pifon.com/3d/js/index.js
You have two functions named Turn(angle) in your original source.
Apparently it starts to work.
Corrected turn function.
function turn(angle){
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.translate(canvas.width/2,canvas.height/2);
ctx.rotate(angle*(Math.PI/180));
ctx.translate(-canvas.width/2,-canvas.height/2);
inform('turn executed (by: '+angle+' degrees)');
drawSaved();
return false;
}
Thanks for your help.
Pifon