I have a problem with the HTML5 canvas element. I use sketch.js so the client can make drawings in a webpage. One of the clients requirement is that he can add 'stamps' with numbers. So I made some modifications to the JS to make this possible. And it works, its possible to add stamps. But when the user switches back to the pen tool and starts drawing again, the numbers dissappears.
I add the stamps using fillText()
$.sketch.tools.text = {
onEvent: function(e) {
switch (e.type) {
case 'mousedown':
case 'touchstart':
this.context.font="16px Verdana";
this.context.fillText(this.stamp, e.pageX - this.canvas.offset().left, e.pageY - this.canvas.offset().top);
break;
}
return true;
},
draw: function(action) {
return true;
}
};
See a demo here:
http://jsfiddle.net/brixion/m5dpwvx5/2/
Hopefully somebody can help me
sketchJS clears and redraws the canvas frequently as determined by its source code. For example each new drawing action by the user will clear & redraw the canvas.
Your this.context.fillText code temporarily "borrows" the sketchJS canvas and draws your text on the canvas. Your text disappears when sketchJS internally decides it need to clear the canvas.
sketchJS does not currently support text, so if you want to permanently put text onto the canvas without having sketchJS erase your text, you will have to modify the source to add the fillText capability.
Alternatively, a workaround might be to add an html canvas element on top-of-and-overlapping your sketchJS canvas (like an html canvas "layer" over your sketchJS canvas). Then draw your text onto the top canvas. This way SketchJS won't erase your desired text.
Note: You must prevent the overlaying canvas from intercepting mouse events. You can do this by setting pointer-events:none; on the top canvas. Here's a link about pointer-events: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events
Related
The problem: I'm trying to create a simple drawing app using p5.js. Instead of the standard cursor image, I'd like to show a circle at my cursor location that represents the size of the drawing brush.
Potential solution 1: Replace the cursor using the cursor() function native to p5.
Why it doesn't work: The p5 cursor function only takes the following parameters:
ARROW, CROSS, HAND, MOVE, TEXT, or WAIT, or path for image
As such, there's no native way to replace the cursor using the ellipse class.
Potential solution 2: Use the noCursor() function and then draw the circle at the cursor location, while also drawing the background, as such:
var brushSize = 50;
function setup() {
createCanvas(1080,720);
noCursor();
}
function draw() {
background(100);
ellipse(mouseX,mouseY,brushSize);
}
Why it doesn't work: While this solution gets the desired effect i.e. replacing the cursor with a circle the size of the brush, the constantly updating background prevents me from actually drawing to the canvas with the brush when I want to.
Is there some way I can replace the cursor without actually drawing the ellipse to the canvas? Is there any way to save and then instantly reload a canvas in p5? I couldn't find such a method searching through the API docs. Any hints are appreciated.
According to the reference, you can pass a URL into the cursor() function to set an image.
If you want to use an image that you draw, you're going to have to draw them ahead of time and save them to files, and then use those files. Something like this:
cursor('images/ellipse-15.png');
Where ellipse-15.png is an image that you generated ahead of time, to match when brushSize is 15, for example.
Btw P5.js is just setting the cursor CSS property. You can read more about it here.
If you want to go with the noCursor() approach and draw the ellipse yourself, you could draw your drawing to a buffer (the createGraphics() function is your friend) and then draw the ellipse on top of that every frame. I'd still probably use a cross cursor just because there's going to be some annoying lag if you draw it yourself.
Create a circular DIV inside the canvas container and show it on top of the actual canvas.
I'm somewhat new to coding. I currently have a code that creates a canvas for a controlled character to move around. So far I have it where if the character runs into the right border of the canvas, it will move the character to the left of the canvas. However I want to have the background change as well, showing the character has entered a new area. How would I go about doing this? The background is currently made with the use of CSS.
First you need to get your canvas into a variable. If it has an ID, you can use that:
var canvas = document.getElementById("YOUR_CANVAS_ID_HERE");
Then use this code to set the canvas' background color:
canvas.style.backgroundColor = "red";
That should be all you need!
I am having trouble finding a good method to limit my mouse to be only able to click on a pre existing line in canvas (stroke width of 3)
What I need to know
how to limit mouse so can only click on pre- existing line, add a dot on click
line is drawn with this function
function createLine(startX:Float, startY:Float, endX:Float, endY:Float)
{
surface.beginPath();
surface.moveTo(startX, startY);
surface.lineTo(endX, endY);
surface.closePath();
surface.strokeStyle = '#ffffff';
surface.lineWidth = 2;
surface.stroke();
}
I am working in haxe, but solution in JS is fine
Thanks in advance.
The only way is for you to keep track of what you have drawn and do the collision/mouse over detection on your own.
If you need your canvas to be highly interactive, you should probably be looking at SVG. http://raphaeljs.com/ is a great library for drawing which will use canvas or SVG, whichever is available.
I have a function in script that draws a rectangular on canvas.I want to clean the rectangular drew in the "if" condition.
I also have text on the canvas(its coordinates are 0,80) and it shouldn't be cleaned. Only the rectangular must be cleaned.
function red_stroke_2(yy)
{
//Red color edges
context.strokeStyle = "#f00";
context.strokeRect(0,yy,800,40);
}
if (Option1==answers[qnumber])
{
red_stroke_2(80);
}
Canvas is "stateless" in the sense that it does not know about the primitives that have been drawn or the calls that have been made. As such it is impossible to undo only a certain drawing call. If you need to modify the drawing, you need to redraw all of the items that you don't want to change. Of course you have the option to change single pixels, so if your text is black and the rectangle is red, you can replace all red pixels, but this won't work so good if antialiasing is enabled and is utterly complicated.
So either redraw the whole area (omit the rectangle drawing but render the text). Or consider using 2 Canvases on top of each other (one with the text, one with the background), then of course you can rerender the background without having to worry about the text.
Last but not least using SVG might be also an alternative, since this is stateful and consists of DOM elements that you can modify/insert/remove and the browser will do the compositing. In that case you would have a rect element and a textelement and you could simply remove the former.
This will put transparent pixels instead of your rectangle:
function clean_red_stroke(yy)
{
context.clearRect(0,yy,800,40);
}
//Call it with the same 'yy' you used in the drawing method
clean_red_stroke(80);
However I think you code could be improved, by using more variables (and consequently a most generic function) for exemple.
I have a JavaScript application that lets users move shapes around a drawing area, and I happen to be using the Google Closure library. In FF/Safari all is good. In IE, as graphic elements are moved, they get selected by the browser (both the moving element and other elements), showing colored dotted background around some elements in unpredictable ways:
http://i.imgur.com/O33MN.png
How can I turn off this behavior in IE?
It's hard to diagnose your problem on the information provided. IE VML is not very well supported and therefore pretty buggy.
In DojoX Drawing, I ran into a similar problem when drawing lines. VML has a bug where you can't drag and resize at the same time – but, you can drag and create at the same time, so I redraw the line, I don't transform it.
Further, I don't attach my click/drag events to the shape, I attach them to the overall main container, detect the id on the mousedown event, then track the mousemove and move the shape via doing a setTransform on the shape's container.
Essentially, because of the weak VML support, you have to be willing to try totally different things to get it to work.
After some experimentation, I found a partial answer.
The goog.events.Event class has a preventDefault method. Simply handle the MOUSEMOVE event on the graphics' element. Then call the event#preventDefault method:
var element = ... // some element
var graphics = goog.graphics.createGraphics('400', '300');
var fill = new goog.graphics.SolidFill('#00ff00', 0.5);
var stroke = new goog.graphics.Stroke(1, 'black');
graphics.drawEllipse(60, 60, 10, 10, stroke, fill);
graphics.drawEllipse(90, 90, 10, 10, stroke, fill);
graphics.render(element);
goog.events.listen(graphics.getElement(), goog.events.EventType.MOUSEMOVE, function(e) {
e.preventDefault();
e.stopPropagation();
});
Clicking inside the graphics element, then dragging no longer selects the circles. Again, this is only necessary on IE.
One minor problem remains. Pressing the mouse outside of the graphics area, then dragging the cursor into the graphics area results in the entire area being selected, or both the area and graphical elements.