With paper.js inserting pointtext to canvas pushes other items away - javascript

I'm trying to create a rectangle and a pointtext element, where the rectangle will be the
text element's container.
Without text element, everything works fine. When text element inserted, rectangle is pushed away. Well, rectangle is displayed at the correct position, but the points where it receives the events are pushed away.
Please see http://jsbin.com/abejim/1
Rectangle's visibility should increase when hovered. Hovering does not affect, but when mouse moved to 580,280 and around , it's visibility increases.
Any suggestions?

That jsbin seems to be working fine for me in Firefox. The rectangle is displayed in the correct location and hovering over the rectangle makes it highlight. Possibly the paper.js code has updated since you asked the question.
It looks like you asked the same question on the paper.js mailing list. For future reference here, the response was:
pointtext takes relative coordinates and you r trying to give absolute coordinates.
try this one:
var size = new paper.Size(125, 75); //SM size to paper size
var rectangle = new paper.Rectangle({ x: 0, y: 0 }, size); //(top_left, bottom_right)
var cornerSize = new paper.Size(10, 10); //rounding of edges
var shape = new paper.Path.RoundRectangle(rectangle, cornerSize);
shape.strokeWidth = 3;
shape.strokeColor = '#525252';
shape.fillColor = '#FFFFFF';
shape.name = 'shape';
var stateNameTxt = new paper.PointText(10, 65);
stateNameTxt.content = state_name;
stateNameTxt.name = 'stateNameTxt';
var state = new paper.Group(); //create group
state.name = state_name;
state.opacity = 0.8;
state.addChild(shape); //add shape to grpup
state.addChild(stateNameTxt); //add pointtext to group

Related

Fill area with fixed size elements

I'm creating an application to calculate how much solar panels would fit on a specific roof.
Users can input the dimensions of their roof.
We only have on size of solar panels available.
I thought a canvas was the way to go but I don't seem to find the information I need..
Requirements
1) Based on the input of the user the canvas should be resized (currently I have a rectangle inside the canvas changing to this size)
2) User should be able to create (and size) objects to put on the roof (chimney, window,..)
3) Based on the open space left solar panels (rectangles) should be automaticly drawn on the canvas
Dimensions and limitations
1px = 2cm
Spacing to edge of roof and object is 7px (14cm)
Solar panel is 169 cm height and 102 cm width
I've checked out the fabric.js library but can't seem to find something close to what I need.
The js I got so far to draw the canvas:
var canvas=document.getElementById("c");
var ctx=canvas.getContext("2d");
var width=50;
var height=35;
var $width=document.getElementById('width');
var $height=document.getElementById('height');
var paneelWidth=101;
var peneelHeight=170;
$width.value=width;
$height.value=height;
draw();
$width.addEventListener("keyup", function(){
width=this.value/2;
draw();
}, false);
$height.addEventListener("keyup", function(){
height=this.value/2;
draw();
}, false);
function draw(){
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.fillRect(10,10,width,height)
}
Update
The canvas now does resize in a dynamic way based on user input.
I also found the function createPattern(), which is bringing me closer to the solution.
I've added this code to generate a pattern of solar panels in the canvas:
function placepanels(direction) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
var img = document.getElementById("paneel");
var pat = ctx.createPattern(img, direction);
var w2 = canvas.width - 7;
var h2 = canvas.height - 7;
ctx.rect(7, 7, w2, h2);
ctx.fillStyle = pat;
ctx.fill();
}
The -7 on width and height is beacause I need 14cm space on each size of the canvas. Hence why I offset the rectangle containing the pattern 7px from left and top. Currently not able to achieve this on right and bottom side.
Current issue
The result I'm getting is not looking correct, it seems like the pattern repeats wrong (to much repeats) or it's not getting the proper size of the image to repeat.
Updated fiddle: https://jsfiddle.net/8e05ghqy/3/
As for the canvas resize, this function would do it:
changeCanvasSize = function( width, height ) {
$('canvas').width(width)
$('canvas').height(height)
}
Example of usage: changeCanvasSize(450,250) would change the canvas size to 450px of width and 250px of height.
I am just resizing the HTML <canvas> element .width( value ) and .height( value ) works for any HTML element.

Custom cursors for canvas caricatures?

I'm making a whiteboard app just for fun and have tools like the brush tool, eraser, etc and I draw on an HTML5 canvas.
I'm trying to implement custom cursors for my tools (like brush, line, square) and was just going to use the CSS cursor property depending on which tool is selected but I'd like sizes to vary depending on the current line width.
For example, in MS Paint you'll notice with the brush and eraser tool, depending on the size of the line width, the cursor is differently sized when drawing on the canvas.
So I have two questions. The first is if I can use CSS still and somehow alternate the cursor size dynamically from JS.
The second is how you would implement this solution by just deleting the cursor and drawing your own on the canvas that follows the mouse movement. I'm a bit concerned that the latter would be quite glitchy and more complex so am hoping that the first one is possible.
Maintaining the position of your own cursor does not work very well on the browsers. By the time you have handled the mouse move, waited for the next animation frame you are one frame behind. (drawing immediately to canvas in the mouse event does help) The is very off putting, even if you set the cursor to "none" so the two do not overlap, the 1/60th of a second can make a big difference from where you see your rendered cursor to and where the hardware cursor (for want of a better name) is.
But it turns out that the browsers Chrome and Firefox allow you to have full control of the hardware cursor image. I have personally exploited it to the limits and it is a robust and tolerant system.
I started with pre made cursors as DataURLs. But now most of my cursors are dynamic. If a control uses the mouse wheel, I add the wheel indicator on the cursor, when using resize cursor, instead of 8 directions N, NE, E, SE, S, SW, W, NW It is created on demand to line up with whatever I happen to be resizing at what ever angle it is. When drawing the cursor is continuously reorienting to avoid covering pixels I may be working on.
To set a custom cursor, set the elements style.cursor to an image URL, followed by two numbers that are the hotspot (Where the click is focused), and a cursor name. I just use the same name "pointer" and generate the image URL on the fly with toDataURL.
Below is a quick example of changing the cursor dynamically. I am unsure what the limits are in terms of size, but so far I haven't wanted a cursor that it has not given me. Some of them, in games have been very big (lol as cursors go) (128*128 pixels +)
Note a slight bug in code. Will return to fix the first rendered word being clipped soon.
The only issue with this is IE does not support this what of doing cursors, so you will need a fallback
// create an image to use to create cursors
var image = document.createElement("canvas");
image.width = 200;
image.height = 14;
image.ctx = image.getContext("2d");
// some graphic cursors
var cursors = [
"url('data:image/png;base64,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') 0 0, cursor",
"url('data:image/png;base64,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') 0 0, cursor ",
"url('data:image/png;base64,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') 0 0, cursor "
];
// Do the stuff that does the stuff
var el = document.getElementById("customeCurs");
var over = false;
// set up canvas rendering
var c = image.ctx;
// some stuff to say and ABC are graphic flags
var stuff = "A C Hello pointy clicky things are great and easy to use A B C B".split(" ");
var tHandle;
var wordPos=0;
function createCursor(){ // creates cursors from the canvas
// get a word from the word list
var w = stuff[wordPos % stuff.length];
if(w === "A" || w === "B" || w === "C"){ // display graphics cursor
// just for fun. to much time on
// my hands. I really need a job.
var datURL;
switch(w){
case "A":
datURL = cursors[0];
break;
case "B":
datURL = cursors[1];
break;
case "C":
datURL = cursors[2];
}
el.style.cursor = datURL;
}else{ // create a dynamic cursor from canvas image
// get the size. Must do this
var size = c.measureText(w).width + 4;
// resize the canvas
image.width = size;
image.height = 36;
c.font = "28px arial black";
c.textAlign ="center";
c.textBaseline = "middle";
c.lineCap = "round";
c.lineJoin = "round";
// Please always give user a visual guide to the hotspot.
// following draws a little arrow to the hotspot.
// Always outline as single colours can get lost to the background
c.lineWidth = 3;
c.strokeStyle = "white";
c.moveTo(1,5);
c.lineTo(1,1);
c.lineTo(5,1);
c.moveTo(1,1);
c.lineTo(8,8);
c.stroke();
c.strokeStyle = "black";
c.lineWidth = 1;
c.moveTo(1,5);
c.lineTo(1,1);
c.lineTo(5,1);
c.moveTo(1,1);
c.lineTo(8,8);
c.stroke();
c.lineWidth = 5;
c.strokeStyle = "black";
c.fillStyle = "White";
// Draw the text outline
c.strokeText(w, image.width / 2, image.height / 2+2);
// and inside
c.fillText(w, image.width / 2, image.height / 2);
// create a cursor and add it to the element CSS curso property
el.style.cursor = "url('"+image.toDataURL("image/png")+"') 0 0 , pointer"; // last two
// numbers are the
// cursor hot spot.
}
// Next word
wordPos += 1;
// if the mouse still over then do it again in 700 ticks of the tocker.
if(over){
tHandle = setTimeout(createCursor,700);
}
}
// mouse over event to start cursor rendering
el.addEventListener("mouseover",function(){
over = true;
if(tHandle === undefined){
createCursor();
}
});
el.addEventListener("mouseout",function(){
over = false; // clean up if the mouse moves out. But leave the cursor
clearTimeout(tHandle);
tHandle = undefined;
});
<div id="customeCurs" >Move Mouse Over ME.</div>
<!-- Some say don't put style in HTML doc! The standards are indifferent. The author is lazy :P -->
<span style="font-size:small;color:#BBB;">Sorry IE again you miss out.</span>

Draw on top of an image using javascript

For a certain image I have a list containing the pixel coordinates of all the points in a polygon segmenting all the objects it contains (look at the image below).
For instance, for the person I have a list l1 = [x0,y0,x1,y1,...,xn,yn], for the cat a list l2 = [x0',y0',x1',y1',...,xk',yk'], and similarly for all the objects.
I have 2 questions:
What is the best javascript library to use to draw on top of an image? Given the raw image I would like to obtain the result seen below.
I would like each segmentation to be visualized only when the mouse hovers on top of it. For this I believe I should bind this drawing function to the mouse position.
I'm thinking at something with the structure below but don't know how to fill the gaps, could you please give me some indication?
$(.container).hover( function(e) {
//get coordinates of mouse
//if mouse is over one object
//draw on top of image the segmentation for that object
});
container is the class of the div containing the image so I should be able to get the coordinates of the mouse since the image starts at the top left corner of the container div.
Simply rebuild the polygons from each array and do a hit test using the mouse position.
First: If you have many arrays defining the shapes it could be smarter to approach it in a more general way instead of using variables for each array as this can soon be hard to maintain. Better yet, an object holding the array and for example id could be better.
Using an object you could do - example:
function Shape(id, points, color) {
this.id = id;
this.points = points;
this.color = color;
}
// this will build the path for this shape and do hit-testing:
Shape.prototype.hitTest = function(ctx, x, y) {
ctx.beginPath();
// start point
ctx.moveTo(this.points[0], this.points[1]);
// build path
for(var i = 2, l = this.points.length; i < l; i += 2) {
ctx.lineTo(this.points[i], this.points[i+1]);
}
ctx.closePath();
return ctx.isPointInPath(x, y);
};
Now you can create new instances with the various point arrays like this:
var shapes = [];
shapes.push(new Shape("Cat", [x0,y0,x1,y1, ...], "rgba(255,0,0,0.5)");
shapes.push(new Shape("Woman", [x0,y0,x1,y1, ...], "rgba(0,255,0,0.5)"));
...
When you get a mouse position simply hit-test each shape:
$(".container").hover( function(e) {
//get corrected coordinates of mouse to x/y
// redraw canvas without shapes highlighted
for(var i = 0, shape; shape = shapes[i]; i++) { // get a shape from array
if (shape.hitTest(ctx, x, y)) { // is x/y inside shape?
ctx.fillStyle = shape.color; // we already have a path
ctx.fill(); // when testing so just fill
// other tasks here...
break;
}
}
});
check this Link it might be slow your problem.
Include necessary javascript library files
jquery.min.js,raphael.min.js,json2.min.js,raphael.sketchpad.js
To create an editor
<div id="editor"></div>
<form action="save.php" method="post">
<input type="hidden" name="data" />
<input type="submit" value="Save" />
</form>
<script type="text/javascript">
var sketchpad = Raphael.sketchpad("editor", {
width: 400,
height: 400,
editing: true
});
// When the sketchpad changes, update the input field.
sketchpad.change(function() {
$("#data").val(sketchpad.json());
});
</script>

Drawing a timeline from div to div with canvas

I have the following div markup
<div data-x="-1000" data-y="-1500">
// content
</div>
<div data-x="0" data-y="-1500">
// content
</div>
And I have many of this divs with different data-x and data-y value depending on their position.
What I want to achieve here is to draw something like a timeline between the divs so div1 line to div2 line to div 3 etc,,
I want this to be done automatically So I am trying to make a loop for it but my javascript/jquery knowledge is not that good. Could someone point me in the good direction?
what I have now is
function drawTimeline() {
var divs = document.getElementsByTagName('div');
var canvas = document.getElementById('timeline');
// Make sure we don't execute when canvas isn't supported
if (canvas.getContext){
// use getContext to use the canvas for drawing
var ctx = canvas.getContext('2d');
var prevCoord = {};
for (var i = -1; div = divs[++i]; ) {
if (div.dataset.x && div.dataset.y) {
var x = parseInt(div.dataset.x);
var y = parseInt(div.dataset.y);
if ({} !== prevCoord) {
ctx.beginPath();
ctx.lineWidth="5";
ctx.strokeStyle="purple"; // Purple path
ctx.moveTo(prevCoord.x, prevCoord.y);
ctx.lineTo(x, y);
ctx.closePath();
ctx.stroke()
}
prevCoord.x = x;
prevCoord.y = y;
}
}
} else {
alert('You need Safari or Firefox 1.5+ to see this.');
}
}
unfortunately the line is not correct its like a linear line and thats it.. can someone help me out with this?
You have the right idea, but your problem is that canvas does not draw at negative coordinates.
Therefore, you must map all your data-x and data-y into positive coordinates.
Here's a function that maps your negative values into positive values:
function mapRange(value, sourceLow, sourceHigh, mappedLow, mappedHigh) {
return mappedLow + (mappedHigh - mappedLow) * (value - sourceLow) / (sourceHigh - sourceLow);
}
So in your example to map a data-x value of -300 into an onscreen range of 0-1000 can do this:
var x = mapRange(-300, -1500,0, 0,1000); // The mapped x is 466.66.
You must reposition your divs to the mapped x,y coordinates which you can do with CSS.
An alternative is to use SVG which creates actual DOM elements that can be positioned at negative coordinates.

Calling several functions using JavaScript's window.onload attribute

I have the following code in the index.html page of my site, which when the page loads, draws a number of images to the HTML5 canvas:
window.onload = function(){
var sources = {};
sources[0] = document.getElementById("building").src,
sources[1] = document.getElementById("chair").src,
sources[2] = document.getElementById("drink").src,
sources[3] = document.getElementById("food").src,
sources[4] = document.getElementById("fridge").src,
sources[5] = document.getElementById("land").src,
sources[6] = document.getElementById("money").src,
sources[7] = document.getElementById("oven").src,
sources[8] = document.getElementById("table").src,
sources[9] = document.getElementById("van").src,
sources[10] = document.getElementById("burger").src,
sources[11] = document.getElementById("chips").src,
sources[12] = document.getElementById("drink").src,
sources[13] = document.getElementById("franchiseFee").src,
sources[14] = document.getElementById("wages").src,
sources[15] = document.getElementById("admin").src,
sources[16] = document.getElementById("cleaners").src,
sources[17] = document.getElementById("electricity").src,
sources[18] = document.getElementById("insurance").src,
sources[19] = document.getElementById("manager").src,
sources[20] = document.getElementById("rates").src,
sources[21] = document.getElementById("training").src,
sources[22] = document.getElementById("water").src,
sources[23] = document.getElementById("burger").src,
sources[24] = document.getElementById("chips").src,
sources[25] = document.getElementById("drink").src,
sources[26] = document.getElementById("creditors").src,
sources[27] = document.getElementById("electricity").src,
sources[28] = document.getElementById("food").src,
sources[29] = document.getElementById("hirePurchase").src,
sources[30] = document.getElementById("loan").src,
sources[31] = document.getElementById("overdraft").src,
sources[32] = document.getElementById("payeTax").src,
sources[33] = document.getElementById("tax").src
loadImages(sources, drawImage);
};
Sources is the array that I'm using to hold the images in JavaScript so that they can be drawn to the canvas once they've been loaded from a hidden section in my HTML.
This function currently works exactly as it's intended- it has a call to the loadImages function, which loads the images from a hidden section in the HTML into the JavaScript array, and calls the drawImage function on each of the images in the array.
But I also have another function that I want to be called with the window.onload:
The function I want to add to window.onload is this:
function drawGameElements(){
/* Draw a line for the 'score bar'. */
context.moveTo(0, 25);
context.lineTo(1000, 25);
context.stroke();
/* Draw current level/ total levels on the left, and current score on the right. */
context.font = "11pt Calibri"; /* Text font & size */
context.strokeStyle = "black"; /* Font colour */
context.strokeText(currentLevel + "/" + totalLevels, 10, 15);
context.strokeText(currentScore, 950, 15);
}
I tried adding a call to the function just below the loadImages(sources, drawImage); line in window.onload = function(){};
So that I now have:
window.onload = function(){
...
loadImages(sources, drawImage);
drawGameElements();
};
Although this partially works, in that it draws the line across the top of the canvas for the 'score bar' and writes "1/3" for the levels on the left hand side of the canvas just above the line, for some reason it doesn't draw the current score on the right hand side.
Also, as soon as I click on one of the images that's been drawn to the canvas, to drag and drop it around the canvas, the 'score bar' then disappears from the canvas completely.
Does anyone know why this is? How can I get the score bar to remain visible throughout the duration of the game, no matter what else happens on the canvas? Also, how can I get the currentScore variable to be displayed?
I would instead use a callback inside of loadImages to call drawGameElements. That way drawGameElements only runs after loadImages is finished. It sounds like you've created a race condition with your two functions.
If I where you, I would create the score bar outside of the canvas. Set its position to absolute and let it hover above the canvas at the desired location. That way you can just access it as HTML elements and do not need to worry about redrawing.
The major advantage of using HTML elements for these displays is that you don't need to redraw them, for example after moving the images around on the canvas. You also don't have to worry about how to refresh the values (on a canvas, just painting new values over the old ones will not be enough). This way you can just store the values in HTML elements and go wild on the canvas, knowing the score will always stay on top.

Categories