I have canvas with svg path on it. I want to do something like this:
http://jsfiddle.net/tbqrn/
var canvas = new fabric.Canvas('c');
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.rect(10,10,150,150);
ctx.rect(180,10,200,200);
ctx.closePath();
ctx.stroke();
ctx.clip();
fabric.Image.fromURL(img01URL, function(oImg) {
oImg.scale(.25);
oImg.left = 50;
oImg.top = 100;
canvas.add(oImg);
canvas.renderAll();
});
fabric.Image.fromURL(img02URL, function(oImg) {
oImg.scale(.25);
oImg.left = 300;
oImg.top = 100;
canvas.add(oImg);
canvas.renderAll();
});
but with one difference: the image after leaving one area should immediately appear in another one.
How can I do it?
This is not doable with a single canvas. The only way I can think of that works is this:
Have two canvases with two different images and "synchronize" the position of the image between them. You actually have to use two images.
HTML:
<canvas id="c1" width="200" height="400"></canvas>
<canvas id="c2" width="200" height="400"></canvas>
CSS:
#c1, #c2 {
border: 1px solid #ccc;
}
#c2 {
margin-left: 20px;
}
.canvas-container {
float: left;
}
JS:
var offsetLeft = 220; // #c1 width + #c2 margin-left
var canvas1 = new fabric.Canvas('c1');
var canvas2 = new fabric.Canvas('c2');
var c1Img, c2Img;
fabric.Image.fromURL(img01URL, function(oImg) {
c1Img = oImg;
c1Img.scale(.25);
c1Img.left = 0;
c1Img.top = 0;
c1Img.hasControls = false;
c1Img.hasRotatingPoint = false;
canvas1.add(c1Img);
canvas1.renderAll();
});
fabric.Image.fromURL(img01URL, function(oImg) {
c2Img = oImg;
c2Img.scale(.25);
c2Img.left = -offsetLeft;
c2Img.top = 0;
c2Img.hasControls = false;
c2Img.hasRotatingPoint = false;
canvas2.add(c2Img);
canvas2.renderAll();
});
canvas1.on('object:moving', function(e) {
c2Img.set({left: e.target.left -offsetLeft, top: e.target.top});
c2Img.setCoords();
canvas2.renderAll();
});
canvas2.on('object:moving', function(e) {
c1Img.set({left: e.target.left + offsetLeft, top: e.target.top});
c1Img.setCoords();
canvas1.renderAll();
});
Test it here: http://jsfiddle.net/se9sw1d8/2/
Related
So I tried to make it so that whenever an image is clicked it will draw a circle on a canvas. The image and the canvas are suppose to overlay. However, I have a problem when I have
cnvs.style.position = 'absolute'; active all of my canvas' are stacked on each other on the first image. So if I were to click other images the circle would be drawn on the first image but not on the image clicked. However, if I comment out cnvs.style.position = 'absolute'; the canvas is being connected to the bottom of the image instead of being overlaid. I need to make it so that each canvas and image are overlaid so that when one image is clicked a circle will appear. I'm thinking I have a css problem, but I'm not sure how to fix it.
document.body.onload = addElement;
function addElement() {
// image path
const imagePath = ['https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fen%2F8%2F84%2FAssociation_of_Gay_and_Lesbian_Psychiatrists_logo.jpg&f=1&nofb=1', 'https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fstatic01.nyt.com%2Fnewsgraphics%2F2016%2F07%2F14%2Fpluto-one-year%2Fassets%2Ficon-pluto.png&f=1&nofb=1', 'https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Ftse4.mm.bing.net%2Fth%3Fid%3DOIP.oFxADNN67dYP-ke5xg7HbQHaHG%26pid%3DApi&f=1', 'https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fmedia.glassdoor.com%2Fsqll%2F1065746%2Felevation-church-squarelogo-1453223965790.png&f=1&nofb=1'];
for (const image of imagePath) {
// get the item id of an image
var slice = image.slice(26, 34);
var id = image;
var hdnName = document.getElementById("sendServ");
const img = document.createElement("img");
img.src = image;
img.classList.add("new");
img.id = slice;
const cnvs = document.createElement("canvas");
cnvs.classList.add("suiteiCanvas");
// cnvs.style.position = 'absolute';
cnvs.style.left = img.offsetLeft + "px";
cnvs.style.top = img.offsetTop + "px";
cnvs.style.display = 'none';
var ctx = cnvs.getContext("2d");
ctx.clearRect(0, 0, cnvs.width, cnvs.height);
ctx.beginPath();
ctx.arc(100, 75, 50, 0, 2 * Math.PI, false);
ctx.lineWidth = 15;
ctx.strokeStyle = '#FF0000';
ctx.stroke();
var div = document.createElement("div");
var div1 = document.createElement("div");
div.id = id;
div1.id = '1';
div.classList.add("image");
img.onclick = function draw() {
cnvs.style.display = '';
hdnName.value = img.id;
};
cnvs.onclick = function remove() {
cnvs.style.display = 'none';
hdnName.value = null;
};
document.getElementById('suitei-slider').appendChild(div);
document.getElementById(image).appendChild(img);
document.getElementById(image).appendChild(cnvs);
}
}
// slick slider
canvas.suiteiCanvas{
height: auto;
width: auto;
max-height: 200px;
max-width: 150px;
margin-left: 100px;
margin-right: 100px;
border:3px solid rgb(20, 11, 11);
}
#draw-btn {
font-size: 14px;
padding: 2px 16px 3px 16px;
margin-bottom: 8px;
}
img.new {
height: auto;
width: auto;
max-height: 200px;
max-width: 150px;
margin-left: 100px;
margin-right: 100px;
border:3px solid rgb(20, 11, 11);
}
<div class="multiple-items" id="suitei-slider"></div>
<input type="hidden" id="sendServ">
You need to set your canvases in position: absolute inside a container in position: relative so that your canvases are still contained in the container. Since the containers are not in position: absolute, they don't overlay, but their content will, so your canvases will overlay with the images.
Then, you have to center you canvases (I suspect), so I set the canvases dimensions (for now it's hard coded) and fixed the x position of the circle.
I hope it is what you were looking for.
document.body.onload = addElement;
function addElement() {
// image path
const imagePath = ['https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fen%2F8%2F84%2FAssociation_of_Gay_and_Lesbian_Psychiatrists_logo.jpg&f=1&nofb=1', 'https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fstatic01.nyt.com%2Fnewsgraphics%2F2016%2F07%2F14%2Fpluto-one-year%2Fassets%2Ficon-pluto.png&f=1&nofb=1', 'https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Ftse4.mm.bing.net%2Fth%3Fid%3DOIP.oFxADNN67dYP-ke5xg7HbQHaHG%26pid%3DApi&f=1', 'https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fmedia.glassdoor.com%2Fsqll%2F1065746%2Felevation-church-squarelogo-1453223965790.png&f=1&nofb=1'];
for (const image of imagePath) {
// get the item id of an image
var slice = image.slice(26, 34);
var id = image;
var hdnName = document.getElementById("sendServ");
const img = document.createElement("img");
img.src = image;
img.classList.add("new");
img.id = slice;
const cnvs = document.createElement("canvas");
cnvs.classList.add("suiteiCanvas");
// cnvs.style.position = 'absolute';
cnvs.style.left = img.offsetLeft + "px";
cnvs.style.top = img.offsetTop + "px";
cnvs.style.display = 'none';
cnvs.width = 150;
cnvs.height = 150;
var ctx = cnvs.getContext("2d");
ctx.clearRect(0, 0, cnvs.width, cnvs.height);
ctx.beginPath();
ctx.arc(75, 75, 50, 0, 2 * Math.PI, false);
ctx.lineWidth = 15;
ctx.strokeStyle = '#FF0000';
ctx.stroke();
var div = document.createElement("div");
var div1 = document.createElement("div");
div.id = id;
div1.id = '1';
div.classList.add("image");
img.onclick = function draw() {
cnvs.style.display = '';
hdnName.value = img.id;
};
cnvs.onclick = function remove() {
cnvs.style.display = 'none';
hdnName.value = null;
};
document.getElementById('suitei-slider').appendChild(div);
document.getElementById(image).appendChild(img);
document.getElementById(image).appendChild(cnvs);
}
}
// slick slider
.image {
position: relative; /* add this */
user-select: none; /* and this maybe */
}
canvas.suiteiCanvas{
height: auto;
width: auto;
height: 150px;
max-width: 150px;
/*margin-left: 100px;
margin-right: 100px;*/
border:3px solid rgb(20, 11, 11);
position: absolute; /* add this */
}
#draw-btn {
font-size: 14px;
padding: 2px 16px 3px 16px;
margin-bottom: 8px;
}
img.new {
height: auto;
width: auto;
max-height: 200px;
max-width: 150px;
/*margin-left: 100px;
margin-right: 100px;*/
border:3px solid rgb(20, 11, 11);
}
<div class="multiple-items" id="suitei-slider"></div>
<input type="hidden" id="sendServ">
Just in case you wonder what each line means here it is a more clean code and with comments on many lines... for my understanding you code is a little confuse. You should use more times functions to be more readable, etc.
let index = 0;
const display = "table"; // or "grid" if horizontal, but this migh depend where you place the rest of the code, cause i added the style to the body
const x = 0;
const y = 0;
const images = {
height: 50,
width: 50,
url: [
'https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fen%2F8%2F84%2FAssociation_of_Gay_and_Lesbian_Psychiatrists_logo.jpg&f=1&nofb=1',
'https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fstatic01.nyt.com%2Fnewsgraphics%2F2016%2F07%2F14%2Fpluto-one-year%2Fassets%2Ficon-pluto.png&f=1&nofb=1',
'https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Ftse4.mm.bing.net%2Fth%3Fid%3DOIP.oFxADNN67dYP-ke5xg7HbQHaHG%26pid%3DApi&f=1',
'https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fmedia.glassdoor.com%2Fsqll%2F1065746%2Felevation-church-squarelogo-1453223965790.png&f=1&nofb=1'
]
}
function createHTML() {
console.log('E: Execute & R: Request & I: Informative');
//loop to go true all images
document.body.style.display = display;
for (const image of images.url) {
//each image will correspond to a canvas element
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
//each canvas element will has is own properties (in this case all the same)
canvas.id = 'option' + [index];
canvas.height = images.height;
canvas.width = images.width;
canvas.style.padding = '10px';
//function to get the corresponded image of that particular canvas element
drawImages(canvas);
//add an event listener for when a user click on the particular canvas
canvas.addEventListener("click", optionClick, false);
//all html part was handle we can append it to the body
document.body.appendChild(canvas);
index++;
}
}
function drawImages(canvas) {
//we need to use the getContext canvas function to draw anything inside the canvas element
const ctx = canvas.getContext('2d');
const background = new Image();
//This is needed because if the drawImage is called from a different place that the createHTML function
//index value will not be at 0 and it will for sure with an heigher id that the one expected
//so we are using regex to remove all letters from the canvas.id and get the number to use it later
index = canvas.id.replace(/\D/g, '');
//console.log('E: Drawing image ' + index + ' on canvas ' + canvas.id);
//get the image url using the index to get the corresponded image
background.src = images.url[index];
//no idea why but to place the image, we need to use the onload event
//https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage
background.onload = function() {
ctx.drawImage(background, 0, 0, canvas.width, canvas.height);
}
}
function drawX(canvas) {
const ctx = canvas.getContext('2d');
console.log('E: Placing X on canvas ' + canvas.id);
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(images.width, images.height);
ctx.moveTo(images.height, 0);
ctx.lineTo(0, images.width);
ctx.closePath();
ctx.stroke();
}
function clear(canvas) {
console.log('E: clearing canvas ' + canvas.id);
canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height);
drawImages(canvas);
}
function optionClick(e) {
log = true;
const canvas = document.getElementsByTagName('canvas');
for (const option of canvas) {
if (log) console.log('I: User clicked at option ' + e.target.id + ':' + option.id);
log = false;
if (e.target.id === option.id) {
console.log('R: Drawing request at canvas ' + option.id);
drawX(option);
} else {
console.log('R: Clearing request at canvas ' + option.id);
clear(option);
}
}
}
//We start by calling createHTML (that will handle with all HTML elements)
window.onload = createHTML;
canvas.suiteiCanvas {
height: auto;
width: auto;
max-height: 200px;
max-width: 150px;
margin-left: 100px;
margin-right: 100px;
border: 3px solid rgb(20, 11, 11);
}
#draw-btn {
font-size: 14px;
padding: 2px 16px 3px 16px;
margin-bottom: 8px;
}
img.new {
height: auto;
width: auto;
max-height: 200px;
max-width: 150px;
margin-left: 100px;
margin-right: 100px;
border: 3px solid rgb(20, 11, 11);
}
<body></body>
I am trying replace images on the canvas after editing it. I need to maintain the width and height of the original image after replacing it, this is my code :
it replaces the image with the new image to the original height and width of the old image as expected. But if I make some changes to old image and then replace the image the changes are not applied.
I want all the changes made on the old image like its height width and angle to be applied to new image
canvas.loadFromJSON(JSON.parse(json_data), canvas.renderAll.bind(canvas), function(o, object) {
if (object.type == 'image') {
var current_width = object.width;
var current_height = object.height;
object.setSrc(url, function() {
// method#1
object.scaleToWidth(current_width);
object.scaleToHeight(current_height);
canvas.renderAll();
});
}
});
obj.set({
width: current_width,
height: current_height
})
Just set width and height no need to use scaleToWidth and scaleToHeight.
DEMO
var canvas = new fabric.Canvas('canvas1');
fabric.Image.fromURL("https://picsum.photos/200/300?random", function(oImg) {
oImg.set({
left: 30,
top: 30
})
canvas.add(oImg);
});
function changeSrc() {
var json_data = canvas.toJSON();
canvas.loadFromJSON(json_data, canvas.renderAll.bind(canvas), function(o, object) {
if (object.type == 'image') {
var current_width = object.width;
var current_height = object.height;
object.setSrc("https://i.imgur.com/4yOoOzl.jpg", function(obj) {
obj.set({
width: current_width,
height: current_height
})
canvas.renderAll();
});
}
});
}
canvas {
border:1px dotted black;
}
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<button onclick="changeSrc()">Change Src</button>
<canvas id="canvas1" width="400" height="400" style=""></canvas>
I have this jsfiddle : http://jsfiddle.net/seekpunk/JDU9f/1/
what I want is when the user do a selection the selected part is zoomed in .Is there anyway to achieve this ?
this is the code so far :
var canvas = document.getElementById("MyCanvas");
var ctx = canvas.getContext('2d'),
w = canvas.width,
h = canvas.height,
x1,
y1,
isDown = false;
var img = new Image();
img.src = "http://www.stockfreeimages.com/static/homepage/female-chaffinch-free-stock-photo-106202.jpg";
canvas.onmousedown = function (e) {
var rect = canvas.getBoundingClientRect();
x1 = e.clientX - rect.left;
y1 = e.clientY - rect.top;
isDown = true;
}
canvas.onmouseup = function () {
isDown = false;
}
canvas.onmousemove = function (e) {
if (!isDown) return;
var rect = canvas.getBoundingClientRect(),
x2 = e.clientX - rect.left,
y2 = e.clientY - rect.top;
ctx.clearRect(0, 0, w, h);
ctx.drawImage(img, 0, 0, w, h);
ctx.strokeRect(x1, y1, x2 - x1, y2 - y1);
}
img.onload = function () {
ctx.drawImage(img, 0, 0, w, h);
};
I can make the selection but how can i zoom the selected part only ? like this example : http://canvasjs.com/docs/charts/basics-of-creating-html5-chart/zooming-panning/
For those looking for zooming functionality without the use of a canvas, here's a pretty foolproof solution using a simple <img />:
$(window).on("load",function() {
//VARS===================================================
var zoom = {
zoomboxLeft:null, zoomboxTop:null, //zoombox
cursorStartX:null, cursorStartY:null, //cursor
imgStartLeft:null, imgStartTop:null, //image
minDragLeft:null,maxDragLeft:null, minDragTop:null,maxDragTop:null
};
//KEY-HANDLERS===========================================
$(document).keydown(function(e) {
if (e.which==32) {e.preventDefault(); if (!$(".zoombox img").hasClass("moving")) {$(".zoombox img").addClass("drag");}} //SPACE
});
$(document).keyup(function(e) {
if (e.which==32) {if (!$(".zoombox img").hasClass("moving")) {$(".zoombox img").removeClass("drag");}} //SPACE
});
//RESET IMAGE SIZE=======================================
$(".reset").on("click",function() {
var zoombox = "#"+$(this).parent().attr("id")+" .zoombox";
$(zoombox+" img").css({"left":0, "top":0, "width":$(zoombox).width(), "height":$(zoombox).height()});
}).click();
//ZOOM&DRAG-EVENTS=======================================
//MOUSEDOWN----------------------------------------------
$(".zoombox img").mousedown(function(e) {
e.preventDefault();
$(".zoombox img").addClass("moving");
var selector = $(this).next();
var zoombox = $(this).parent();
$(zoombox).addClass("active");
//store zoombox left&top
zoom.zoomboxLeft = $(zoombox).offset().left + parseInt($(zoombox).css("border-left-width").replace(/\D+/,""));
zoom.zoomboxTop = $(zoombox).offset().top + parseInt($(zoombox).css("border-top-width").replace(/\D+/,""));
//store starting positions of cursor (relative to zoombox)
zoom.cursorStartX = e.pageX - zoom.zoomboxLeft;
zoom.cursorStartY = e.pageY - zoom.zoomboxTop;
if ($(".zoombox img").hasClass("drag")) {
//store starting positions of image (relative to zoombox)
zoom.imgStartLeft = $(this).position().left;
zoom.imgStartTop = $(this).position().top;
//set drag boundaries (relative to zoombox)
zoom.minDragLeft = $(zoombox).width() - $(this).width();
zoom.maxDragLeft = 0;
zoom.minDragTop = $(zoombox).height() - $(this).height();
zoom.maxDragTop = 0;
} else {
//set drag boundaries (relative to zoombox)
zoom.minDragLeft = 0;
zoom.maxDragLeft = $(zoombox).width();
zoom.minDragTop = 0;
zoom.maxDragTop = $(zoombox).height();
//activate zoom-selector
$(selector).css({"display":"block", "width":0, "height":0, "left":zoom.cursorStartX, "top":zoom.cursorStartY});
}
});
//MOUSEMOVE----------------------------------------------
$(document).mousemove(function(e) {
if ($(".zoombox img").hasClass("moving")) {
if ($(".zoombox img").hasClass("drag")) {
var img = $(".zoombox.active img")[0];
//update image position (relative to zoombox)
$(img).css({
"left": zoom.imgStartLeft + (e.pageX-zoom.zoomboxLeft)-zoom.cursorStartX,
"top": zoom.imgStartTop + (e.pageY-zoom.zoomboxTop)-zoom.cursorStartY
});
//prevent dragging in prohibited areas (relative to zoombox)
if ($(img).position().left <= zoom.minDragLeft) {$(img).css("left",zoom.minDragLeft);} else
if ($(img).position().left >= zoom.maxDragLeft) {$(img).css("left",zoom.maxDragLeft);}
if ($(img).position().top <= zoom.minDragTop) {$(img).css("top",zoom.minDragTop);} else
if ($(img).position().top >= zoom.maxDragTop) {$(img).css("top",zoom.maxDragTop);}
} else {
//calculate selector width and height (relative to zoombox)
var width = (e.pageX-zoom.zoomboxLeft)-zoom.cursorStartX;
var height = (e.pageY-zoom.zoomboxTop)-zoom.cursorStartY;
//prevent dragging in prohibited areas (relative to zoombox)
if (e.pageX-zoom.zoomboxLeft <= zoom.minDragLeft) {width = zoom.minDragLeft - zoom.cursorStartX;} else
if (e.pageX-zoom.zoomboxLeft >= zoom.maxDragLeft) {width = zoom.maxDragLeft - zoom.cursorStartX;}
if (e.pageY-zoom.zoomboxTop <= zoom.minDragTop) {height = zoom.minDragTop - zoom.cursorStartY;} else
if (e.pageY-zoom.zoomboxTop >= zoom.maxDragTop) {height = zoom.maxDragTop - zoom.cursorStartY;}
//update zoom-selector
var selector = $(".zoombox.active .selector")[0];
$(selector).css({"width":Math.abs(width), "height":Math.abs(height)});
if (width<0) {$(selector).css("left",zoom.cursorStartX-Math.abs(width));}
if (height<0) {$(selector).css("top",zoom.cursorStartY-Math.abs(height));}
}
}
});
//MOUSEUP------------------------------------------------
$(document).mouseup(function() {
if ($(".zoombox img").hasClass("moving")) {
if (!$(".zoombox img").hasClass("drag")) {
var img = $(".zoombox.active img")[0];
var selector = $(".zoombox.active .selector")[0];
if ($(selector).width()>0 && $(selector).height()>0) {
//resize zoom-selector and image
var magnification = ($(selector).width()<$(selector).height() ? $(selector).parent().width()/$(selector).width() : $(selector).parent().height()/$(selector).height()); //go for the highest magnification
var hFactor = $(img).width() / ($(selector).position().left-$(img).position().left);
var vFactor = $(img).height() / ($(selector).position().top-$(img).position().top);
$(selector).css({"width":$(selector).width()*magnification, "height":$(selector).height()*magnification});
$(img).css({"width":$(img).width()*magnification, "height":$(img).height()*magnification});
//correct for misalignment during magnification, caused by size-factor
$(img).css({
"left": $(selector).position().left - ($(img).width()/hFactor),
"top": $(selector).position().top - ($(img).height()/vFactor)
});
//reposition zoom-selector and image (relative to zoombox)
var selectorLeft = ($(selector).parent().width()/2) - ($(selector).width()/2);
var selectorTop = ($(selector).parent().height()/2) - ($(selector).height()/2);
var selectorDeltaLeft = selectorLeft - $(selector).position().left;
var selectorDeltaTop = selectorTop - $(selector).position().top;
$(selector).css({"left":selectorLeft, "top":selectorTop});
$(img).css({"left":"+="+selectorDeltaLeft, "top":"+="+selectorDeltaTop});
}
//deactivate zoom-selector
$(selector).css({"display":"none", "width":0, "height":0, "left":0, "top":0});
} else {$(".zoombox img").removeClass("drag");}
$(".zoombox img").removeClass("moving");
$(".zoombox.active").removeClass("active");
}
});
});
/*CONTAINER-------------------*/
#container {
width: 234px;
height: 199px;
margin-left: auto;
margin-right: auto;
}
/*ZOOMBOX=====================*/
/*IMAGE-----------------------*/
.zoombox {
position:relative;
width: 100%;
height: 100%;
border: 2px solid #AAAAAA;
background-color: #666666;
overflow: hidden;
}
.zoombox img {position:relative;}
.zoombox img.drag {cursor:move;}
.zoombox .selector {
display: none;
position: absolute;
border: 1px solid #999999;
background-color: rgba(255,255,255, 0.3);
}
/*CONTROL---------------------*/
.reset {float:left;}
.info {float:right;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container">
<!--ZOOMBOX-->
<div class="zoombox">
<img src="http://www.w3schools.com/colors/img_colormap.gif" />
<div class="selector"></div>
</div>
<input type="button" class="reset" value="Reset" /><span class="info">Press SPACE to drag</span>
</div>
jsfiddle: http://jsfiddle.net/2nt8k8e6/
The container element can be anything, just place the .zoombox on your webpage and it should work.
You should even be able to put multiple .zoomboxes next to each other in the same container-element. I haven't tested it though.
It's not too complicated, there's not a whole lot of comments, but the variable names are pretty self-explanatory and make the code easy enough to read, and all the jquery-functions can be looked up.
The code is essentially divided into three handlers: .mousedown(), .mousemove(), .mouseup().
- In mousedown some values are stored into variables (like the start-coordinates for the selector), which are used in mousemove and mouseup as a reference.
If you want to know exactly what's happening, just have a look at the code, as I said it's not too difficult.
I'm trying to past multiple images on separate Canvas layers that are stacked upon each other yet the images aren't drawing on the canvas. Can someone help me out with what I am missing?
Thanks
CSS
.positionCanvas{
position: absolute;
left:0;
right:0;
margin-left:auto;
margin-right:auto;
background: rgba(255,255,255,0);
}
#logoCanvas{
position: relative;
}
HTML
<div id="logoCanvas">
<canvas class="positionCanvas" width="300" height="300" id="outerRingCanvas">
</canvas>
<canvas class="positionCanvas" width="300" height="300" id="crossCanvas">
</canvas>
<canvas class="positionCanvas" width="300" height="300" id="innerRingsCanvas">
</canvas>
<canvas class="positionCanvas" width="300" height="300" id="centreCanvas">
</canvas>
</div>
JAVASCRIPT
var outerRing = document.getElementById('outerRingCanvas'),
cross = document.getElementById('crossCanvas'),
innerRings = document.getElementById('innerRingsCanvas'),
centre = document.getElementById('centreCanvas');
var outerCtx = outerRing.getContext('2d'),
crossCtx = cross.getContext('2d'),
innerRingsCtx = innerRings.getContext('2d'),
centreCtx = centre.getContext('2d');
var ctxArray = [outerCtx, crossCtx, innerRingsCtx, centreCtx];
var outerImg = new Image(),
crossImg = new Image(),
innerRingsImg = new Image(),
centreImg = new Image();
var imgArray = [outerImg, crossImg, innerRingsImg, centreImg];
outerImg.src = "logo_ring.png";
crossImg.src = "logo_cross.png";
innerRingsImg.src = "logo_centre_rings.png";
centreImg.src = "logo_centre.png";
placeLogos(ctxArray);
crossCtx.drawImage(crossImg, 0, 0, 300, 300);
function placeLogos(array){
for(var i = 0; i < array.length; i++){
array[i].drawImage(imgArray[i], 100, 100, 100, 100);
array[i].fillStyle = "rgba(233,100,10,0.2)"
array[i].fillRect(0, 0, 300, 300);
}
}
Use the onload mechanism as image loading is asynchronous. If you're not using this the image may not be fully loaded when you try to use them leaving the canvas(es) blank.
...
var imageCount = 4;
outerImg.onload = loader;
crossImg.onload = loader;
innerRingsImg.onload = loader;
centreImg.onload = loader;
outerImg.src = "logo_ring.png";
crossImg.src = "logo_cross.png";
innerRingsImg.src = "logo_centre_rings.png";
centreImg.src = "logo_centre.png";
function loader() {
imageCount--;
if (imageCount === 0) {
placeLogos(ctxArray);
crossCtx.drawImage(crossImg, 0, 0, 300, 300);
}
}
I am trying to save a FLOT chart as an image. The chart is currently being displayed correctly in a div element as follows:
<div id="flotcontainer"></div>
The tool that I am using to save the image is canvas2image. This small library lets you easily save a HTML5 canvas element as an image file. This code is working on my page and I am able to annotate and then save the canvas element:
<canvas width="100" height="100" id="cvs"></canvas>
The problem that I am having is that the canvas2image code requires a canvas element, but my FLOT chart is displayed in a normal div element. What do I need to do to be able to pass the div containing my FLOT chart, instead of the canvas element to be saved? Thanks.
Here is the complete code that I am working on:
<style type="text/css">
#flotcontainer {
width: document.getElementById('flot_widget').offsetWidth;
height: 300px;
text-align: center;
margin: 0 auto;
}
canvas {
display: block;
border: 2px solid #888;
}
</style>
<div id="flotcontainer" style="display:none;" ></div>
<div class="g12">
<canvas width="100" height="100" id="cvs"></canvas>
<div>
<p>
<button id="save">save</button> or <button id="convert">convert to</button> as:
<select id="sel">
<option value="png">png</option>
<option value="jpeg">jpeg</option>
<option value="bmp">bmp</option>
</select><br/>
w : <input type="number" value="300" id="imgW" /> h : <input type="number" value="200" id="imgH" />
</p>
</div>
<div id="imgs">
</div>
</div>
<script>
var canvas, ctx, bMouseIsDown = false, iLastX, iLastY,
$save, $imgs,
$convert, $imgW, $imgH,
$sel;
function init () {
canvas = document.getElementById('cvs');
ctx = canvas.getContext('2d');
$save = document.getElementById('save');
$convert = document.getElementById('convert');
$sel = document.getElementById('sel');
$imgs = document.getElementById('imgs');
$imgW = document.getElementById('imgW');
$imgH = document.getElementById('imgH');
bind();
draw();
}
function bind () {
canvas.onmousedown = function(e) {
bMouseIsDown = true;
iLastX = e.clientX - canvas.offsetLeft + (window.pageXOffset||document.body.scrollLeft||document.documentElement.scrollLeft);
iLastY = e.clientY - canvas.offsetTop + (window.pageYOffset||document.body.scrollTop||document.documentElement.scrollTop);
}
canvas.onmouseup = function() {
bMouseIsDown = false;
iLastX = -1;
iLastY = -1;
}
canvas.onmousemove = function(e) {
if (bMouseIsDown) {
var iX = e.clientX - canvas.offsetLeft + (window.pageXOffset||document.body.scrollLeft||document.documentElement.scrollLeft);
var iY = e.clientY - canvas.offsetTop + (window.pageYOffset||document.body.scrollTop||document.documentElement.scrollTop);
ctx.moveTo(iLastX, iLastY);
ctx.lineTo(iX, iY);
ctx.stroke();
iLastX = iX;
iLastY = iY;
}
};
$save.onclick = function (e) {
var type = $sel.value,
w = $imgW.value,
h = $imgH.value;
Canvas2Image.saveAsImage(canvas, w, h, type);
}
$convert.onclick = function (e) {
var type = $sel.value,
w = $imgW.value,
h = $imgH.value;
$imgs.appendChild(Canvas2Image.convertToImage(canvas, w, h, type))
}
}
function draw () {
ctx.fillStyle = '#ffffff';
ctx.fillRect(0, 0, 600, 400);
ctx.fillStyle = 'red';
ctx.fillRect(10, 10, 50, 50);
}
onload = init;
</script>
To get the canvas of the Flot chart use
$canvas = $('#flotcontainer').find('canvas.base');
By the way:
You cannot use javascript inside your style element, you have to
set the width by javascript after the page has loaded.
Why are you not using jQuery when you have to load it for the flot plugin?You could simplify $imgs = document.getElementById('imgs'); to $imgs = $('#imgs');.Additionally, beginning variable names with $ should be used for jQuery objects only to avoid confusion between jQuery objects and standard javascript / DOM objects.
You can also get the canvas from the flot plot object itself:
var somePlot = $.plot("#placeholder", [ [0,0],[10,10] ]);
somePlot.getCanvas()