How to load image on page load in Canvas - javascript

Hi I am using canvas for drawing but issue is this on page load I want to show an image on canvas so the user can continue from where he left
<div id="wPaint" style="position:relative; width:100%; height:600px; background-color:white; border:1px solid black; resize: both; ">
</div>
canvas is loaded in this div. if I inspect then canvas code is below image
Thanks for any help.

Introduction
The question is referring to a scenario when you have a canvas and the user can change its content. I assume that this works and you need to be able to save the content of the canvas as an image and load that saved image and draw into the canvas the given image.
Exporting the content
var canvas = document.getElementById("mycanvas"); //you can change this to your image
var img = canvas.toDataURL("image/png");
Saving the image
Once you have successfully created the img variable, you can save it. You can store it into localStorage, like
localStorage.setItem('saved', img)
You can store it differently as well, like sending the image to your server in a POST request, but, for the purpose of this question I aim to have a simple solution that works. It would be another task to store this as a file or something of the like in your server.
Loading the image
let img = document.createElement('img');
img.src = localStorage.getItem('saved');
It is possible that img was not saved yet, like in the first load. You will need to properly handle that case, like
if (img.src) {
//do some stuff
}
Putting an image into a canvas
canvas.getContext('2d').drawImage(img, dx, dy);

Hi I create arrow but issue is arrow not perfect on all direction... top , down , right and left direction arrow not perfect
here it image
here it is my code
_drawLineMove: function (a) {
this._drawShapeMove(a, 1);
var b = this.canvasTempLeftOriginal,
c = this.canvasTempTopOriginal;
//var headlen = 10; // length of head in pixels
a.pageX < b && ((a.x = a.x + a.w), (a.w = -1 * a.w)),
a.pageY < c && ((a.y = a.y + a.h), (a.h = -1 * a.h)),
(this.ctxTemp.lineJoin = "round"),
this.ctxTemp.beginPath(),
console.log(a);
const head_len = 16;
const head_angle = Math.PI / 6;
var dx = (a.x + a.w) - a.x;
var dy = (a.y + a.h) - a.y;
const angle = Math.atan2(dy, dx);
this.ctxTemp.beginPath();
this.ctxTemp.moveTo(a.x, a.y), //fromx , fromy
this.ctxTemp.lineTo(a.x + a.w, a.y + a.h), //tox,toy
this.ctxTemp.stroke();
this.ctxTemp.beginPath();
this.ctxTemp.lineTo((a.x + a.w), (a.y + a.h));
this.ctxTemp.lineTo((a.x + a.w) - head_len * Math.cos(angle - head_angle), (a.y + a.h) - head_len * Math.sin(angle - head_angle));
this.ctxTemp.lineTo((a.x + a.w) - head_len * Math.cos(angle + head_angle), (a.y + a.h) - head_len * Math.sin(angle + head_angle));
this.ctxTemp.closePath(),
this.ctxTemp.stroke();
this.ctxTemp.fill();
},
thanks

Related

Resize multiple objects with JS considering rotate

I'm working on visual editor with objects and user interactions around like move, resize, rotate, etc...
I have resize and rotate functionality in place. Now I have implemented multi-select functionality when user select multiple objects and resize objects keeping the original proportion.
That functionality works very well, however not for rotated objects. I've created a simplified codepen example. Basically the question is - how to adjust resize() function to make sure it works well for rotated objects. To reproduce an issue just click on "Rotate" and then "Increase width & height" once or multiple times.
function resize(incrementX, incrementY, offsetX, offsetY) {
...
}
I'm not sure if this is a valid solution for your problem, but you can undo the rotation before resizing, and reset the rotation afterwards. Like this.
function resize(incrementX, incrementY, offsetX, offsetY) {
var old_r = objmultiple.r
rotate(-objmultiple.r)
var ratioX = (objmultiple.w + incrementX) / objmultiple.w;
var ratioY = (objmultiple.h + incrementY) / objmultiple.h;
objmultiple.x += offsetX;
objmultiple.y += offsetY;
objmultiple.w = objmultiple.w + incrementX;
objmultiple.h = objmultiple.h + incrementY;
[obj1, obj2].forEach(function(obj) {
obj.x = (obj.x - objmultiple.x + offsetX) * ratioX + objmultiple.x;
obj.y = (obj.y - objmultiple.y + offsetY) * ratioY + objmultiple.y;
obj.w *= ratioX;
obj.h *= ratioY;
});
rotate(old_r)
}
Codepen here

Image magnifier in Angular

I am trying to implement a image maginfier on hover.I tried to replicate the code as in w3schools which is purely of Javascript.I am trying to implement the following code in Angular
https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_image_magnifier_glass
I used the above method in typescript and called it from ngOnInit in Angular but i am not able to get any result from the method.I have ensured the id is passed correctly and validated the method is being called .But still not able to get any result .I wish not to use any npm packages for magnifier since most of them had bugs.
component.ts
ngOnInit(){
this.magnify(imgID, zoom)
}
magnify(imgID, zoom) {
var img, glass, w, h, bw;
img = document.getElementById(imgID);
/*create magnifier glass:*/
glass = document.createElement("DIV");
glass.setAttribute("class", "img-magnifier-glass");
/*insert magnifier glass:*/
img.parentElement.insertBefore(glass, img);
/*set background properties for the magnifier glass:*/
glass.style.backgroundImage = "url('" + img.src + "')";
glass.style.backgroundRepeat = "no-repeat";
glass.style.backgroundSize = (img.width * zoom) + "px " + (img.height * zoom) + "px";
bw = 3;
w = glass.offsetWidth / 2;
h = glass.offsetHeight / 2;
/*execute a function when someone moves the magnifier glass over the image:*/
glass.addEventListener("mousemove", moveMagnifier);
img.addEventListener("mousemove", moveMagnifier);
/*and also for touch screens:*/
glass.addEventListener("touchmove", moveMagnifier);
img.addEventListener("touchmove", moveMagnifier);
function moveMagnifier(e) {
var pos, x, y;
/*prevent any other actions that may occur when moving over the image*/
e.preventDefault();
/*get the cursor's x and y positions:*/
pos = getCursorPos(e);
x = pos.x;
y = pos.y;
/*prevent the magnifier glass from being positioned outside the image:*/
if (x > img.width - (w / zoom)) {x = img.width - (w / zoom);}
if (x < w / zoom) {x = w / zoom;}
if (y > img.height - (h / zoom)) {y = img.height - (h / zoom);}
if (y < h / zoom) {y = h / zoom;}
/*set the position of the magnifier glass:*/
glass.style.left = (x - w) + "px";
glass.style.top = (y - h) + "px";
/*display what the magnifier glass "sees":*/
glass.style.backgroundPosition = "-" + ((x * zoom) - w + bw) + "px -" + ((y * zoom) - h + bw) + "px";
}
function getCursorPos(e) {
var a, x = 0, y = 0;
e = e || window.event;
/*get the x and y positions of the image:*/
a = img.getBoundingClientRect();
/*calculate the cursor's x and y coordinates, relative to the image:*/
x = e.pageX - a.left;
y = e.pageY - a.top;
/*consider any page scrolling:*/
x = x - window.pageXOffset;
y = y - window.pageYOffset;
return {x : x, y : y};
}
}
Here is a working stackblitz as per your requirements. It shows the implementation of image zoom functionality mentioned on w3school.
https://stackblitz.com/edit/angular-w3school-image-magnification
You have not shown your html and css files. So, I am not totally sure but the following might be the reason why zoom is not working for you.
Problem is that img-magnifier-glass div element is created using classical DOM method 'document.createElement'. And then, class 'img-magnifier-glass' is applied to it, again using a classical DOM method (setAttribute). But, in angular, styles are encapsulated. So, if you have added a class definition of '.img-magnifier-glass' in app.component.css then that class won't be applied to glass div since it is not mentioned in the template (app.component.html). See this for more info - https://github.com/angular/angular/issues/7845
To fix this, you can either move definition of class '.img-magnifier-glass' to styles.css (Where global styles are defined)
or you can keep the class in app.component.css but use pseudo-selector ::ng-deep with it. Applying the ::ng-deep pseudo-class to any CSS rule completely disables view-encapsulation for that rule. Any style with ::ng-deep applied becomes a global style.
::ng-deep .img-magnifier-glass {
}
or you can stop style encapsulation for component by specifying
#Component({
// ...
encapsulation: ViewEncapsulation.None, //<<<<< this one!
styles: [
// ...
]
})
It will be better will be if you use Renderer2 (https://angular.io/api/core/Renderer2) instead for creating dynamic elements like glass element here. Renderer2 will take care of correctly encapsulating class applied on elements created using it.
I ran into the same issue but for image zoomer which has the same implementation of magnifier. I got it working by tweaking the css and ts code (which was taken from the magnifier and combined with the zoomer). the answer above is not what I am looking for coz I need the zoomed img to be in a different box and not on top of the img itself. Here is the stackblitz code which I modified to suit what I need.
For implementing image magnification feature like W3School and Amazon in Angular, you can use npm package ng-img-magnifier.
Here is the working DEMO.
<ng-img-magnifier
[thumbImage]='img' [fullImage]='img2'
[top]='top' [right]='right'
[lensWidth]='lensewidth' [lensHeight]='lensheight'
[imgWidth]='imgWidth' [imgHeight]='imgheight'
[resultWidth]='resultWidth' [resultHeight]='resultheight'
>
</ng-img-magnifier>
This package comes with full customization options.
Hopefully this will resolve your issue.

Display value in canvas during mouseover

Dear JavaScript users,
I need to be able to:
load a png image and display it on a canvas
store its original pixel values
transform the pixel values to represent new colours
display the original values on the screen when the user moves their cursor over the image
This may sound like a slightly odd thing to do, but the original pixel values in my live system will contain encoded data that I need to retain, and display on the screen after whatever pixel value manipulation is subsequently carried out. I need to change the colour mapping after the initial loading of the image to make it more pleasing to the eye, but need to display the original values on the screen.
My method works when displaying some simple geometrical shapes on the canvas, but as soon as I try to use a png image it stops working. Can anyone help me to understand why this is?
An example (without the pixel value transformation) that works with the simple shapes is here:
http://jsfiddle.net/DV9Bw/1219/
If you comment out lines 24 - 29, and uncomment lines 32 - 40 so that it loads in a png, it stops working. The png file loads, but the data values are no longer shown on the screen.
Any suggestions as to why it breaks when I use a png would be welcome; any suggestions on how to fix it would be even more welcome!
Many thanks in advance for any help.
David
function findPos(obj) {
var curleft = 0, curtop = 0;
if (obj.offsetParent) {
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj = obj.offsetParent);
return { x: curleft, y: curtop };
}
return undefined;
}
function rgbToHex(r, g, b) {
if (r > 255 || g > 255 || b > 255)
throw "Invalid color component";
return ((r << 16) | (g << 8) | b).toString(16);
}
var example = document.getElementById('example');
var context = example.getContext('2d');
// The squares works
context.fillStyle = "rgb(255,0,0)";
context.fillRect(0, 0, 50, 50);
context.fillStyle = "rgb(0,0,255)";
context.fillRect(55, 0, 50, 50);
// End of squares
/*
// Replacing the squares section above with this
// png image stops the mouseOver from working, Why?
var imageObj = new Image();
imageObj.onload = function() {
context.drawImage(imageObj, 0, 0, imageObj.width, imageObj.height, 0, 0, imageObj.width*4, imageObj.height*4);
};
imageObj.src = 'http://dplatten.co.uk/mouseOver/skin_dose_map.png';
*/
var originalValues = new Array();
originalValues = context.getImageData(0,0,280,360).data;
$('#example').mousemove(function(e) {
var pos = findPos(this);
var x = e.pageX - pos.x;
var y = e.pageY - pos.y;
var coord = "x=" + x + ", y=" + y;
var c = this.getContext('2d');
var r = originalValues[(y*280 + x)*4];
var g = originalValues[(y*280 + x)*4+1];
var b = originalValues[(y*280 + x)*4+2];
$('#status').html(coord + "<br>" + r + "," + g + "," + b);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="example" width="280" height="360"></canvas>
<div id="status"></div>
The problem is two-fold
First of all, these two line:
var originalValues = new Array();
originalValues = context.getImageData(0,0,280,360).data;
are being run before you paint the image since it's waiting for the image to load still.
Then, if would move the context.getImageData() to inside the imgObject.onload-function, you'd run into another problem namely, you can't run getImageData() on an image that is not on the same location as the file that is running the script. You will get the following message:
Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.
If you put the image on the same server and move the getImageData() call inside the onload-function, it should work.

Rotate links along a circle

I'm trying to make a website with links rotating around a circle. (Something like this) http://i.imgur.com/i9DzASw.jpg?1 with the different images and texts leading to different urls. The image is one unified image that also rotates as the user scrolls. Is there anyway I can do this? Also is there a way to make the page height infinite so that the user never gets to the bottom of the page as they scroll? Thanks!
Here's the jsfiddle and the code that allows for the rotation of the image.
http://jsfiddle.net/kDSqB/135/
var $cog = $('#cog'),
$body = $(document.body),
bodyHeight = $body.height();
$(window).scroll(function () {
$cog.css({
'transform': 'rotate(' + ($body.scrollTop() / bodyHeight * 30000) + 'deg)'
});
});
http://jsfiddle.net/Fezjh/1/
I have coloured the div to make it easier to understand how to do it - but you need to think carefully about compatiblity issues (older browsers etc.)
Just remove the background colour to get your desired effect.
A better way would be to split the image into divs and put those divs up against each other.
check http://www.gdrtec.co.uk - you will notice 4 images butted up against each other form the start menu - it would be easy to rotate the containing div and everything will still work as it should.
The code below is just for demonstration purposes and should be replaced with more robust solution.
$('#link1').click(function(){
alert("openURL");
});
Also consider making sure people don't have to rely on javascript for your site to work.
See this : http://jsfiddle.net/F8GTP/, and this final version : http://jsfiddle.net/MjnxP/.
Use WheelEvent like this for infinite scroll :
var $cog = $('#cog'),
$body = $(document.body),
bodyHeight = $body.height(),
rotate = 1;
var wheelEvent = function (event) {
var delta = 0;
if (event.wheelDelta) { delta = event.wheelDelta/120; } else if (event.detail) { delta = -event.detail/3; }
if (delta) {
rotate += delta * 1.12; //<== Increase speed.
console.log(rotate, delta);
$cog.css({ 'transform': 'rotate(' + rotate + 'deg)'});
}
if (event.preventDefault) { event.preventDefault(); }
event.returnValue = false;
};
window.onmousewheel = wheelEvent;
if (window.addEventListener) { window.addEventListener('DOMMouseScroll', wheelEvent, false); }
For detect link use canvas with "collision image", and this is final version :
$cog.click(function(e) {
if (rotate !== lastrotate) {
//http://creativejs.com/2012/01/day-10-drawing-rotated-images-into-canvas/
context.save();
context.translate((image.width/2), (image.height/2));
context.rotate(rotate * Math.PI/180);
context.drawImage(image, -(image.width/2), -(image.height/2));
context.restore();
lastrotate = rotate;
}
var x = e.pageX, y = e.pageY;
console.log(x, y);
var color = context.getImageData(x, y, 1, 1).data;
// context.fillRect(x-5, y-5, 1+10, 1+10); <== See cursor position
if (color[0] == 255 && color[1] == 255 && color[2] == 255) { //white = rgb(255, 255, 255);
alert("click");
}
});
function setPixel(imageData, x, y, r, g, b, a) {
index = (x + y * imageData.width) * 4;
imageData.data[index+0] = r;
imageData.data[index+1] = g;
imageData.data[index+2] = b;
imageData.data[index+3] = a;
}
var canvas = document.getElementById('canvas'),
context = canvas.getContext('2d'),
image = new Image(),
lastrotate = null;
image.onload = function(){
canvas.width = image.width;
canvas.height = image.height;
context.drawImage(image, 0, 0, image.width, image.height);
};
// http://i.imgur.com/UfjbW5l.png I use base64 for get image because else console return security error with "getImageData".
image.src = "data:image/png;base64,iVBORw0K...";
For "image.src", use your image in YOUR DOMAIN or use Base64 else this script return security error for convert image to base64 see : http://www.base64-image.de/.
If position of cog isn't (0, 0) replace actual line to this line :
var x_pos = 200, y_pos = 200; // No use .position() or .offset() for get this, or use parent element position.
var x = e.pageX - x_pos, y = e.pageY - y_pos;

jQuery image hover effect

I'm trying to achieve this effect with jQuery.
I wrote some of the code, but it's buggy (move to the bottom-right corder and you'll see).
check it out
Basically, if there's an already-built jQuery plugin that you know of that does this, I'd be very happy using it, if not, any help with my formula would be appreciated. This is what I get for not paying attention in Maths classes :)
Thanks in advance.
Maikel
Overall I think this is what you're looking for:
$.fn.sexyImageHover = function() {
var p = this, // parent
i = this.children('img'); // image
i.load(function(){
// get image and parent width/height info
var pw = p.width(),
ph = p.height(),
w = i.width(),
h = i.height();
// check if the image is actually larger than the parent
if (w > pw || h > ph) {
var w_offset = w - pw,
h_offset = h - ph;
// center the image in the view by default
i.css({ 'margin-top':(h_offset / 2) * -1, 'margin-left':(w_offset / 2) * -1 });
p.mousemove(function(e){
var new_x = 0 - w_offset * e.offsetX / w,
new_y = 0 - h_offset * e.offsetY / h;
i.css({ 'margin-top':new_y, 'margin-left':new_x });
});
}
});
}
You can test it here.
Notable changes:
new_x and new_y should be divided by the images height/width, not the container's height/width, which is wider.
this is already a jQuery object in a $.fn.plugin function, no need to wrap it.
i and p were also jQuery objects, no need to keep wrapping them
no need to bind mousemove on mouseenter (which rebinds) the mousemove will only occur when you're inside anyway.
Nick Craver beat me to an answer by about 10 minutes, but this is my code for this, using background-image to position the image instead of an actual image.
var img = $('#outer'),
imgWidth = 1600,
imgHeight = 1200,
eleWidth = img.width(),
eleHeight = img.height(),
offsetX = img.offset().left,
offsetY = img.offset().top,
moveRatioX = imgWidth / eleWidth - 1,
moveRatioY = imgHeight / eleHeight - 1;
img.mousemove(function(e){
var x = imgWidth - ((e.pageX - offsetX) * moveRatioX),
y = imgHeight - ((e.pageY - offsetY) * moveRatioY);
this.style.backgroundPosition = x + 'px ' + y + 'px';
});
The huge amount of variables are there because the mousemove event handler has to be as efficient as possible. It's slightly more restrictive, because you need to know the dimensions, but I think the code can be easily altered to work with imgs for which the size can be calculated easily.
A simple demo of this: http://www.jsfiddle.net/yijiang/fq2te/1/

Categories