Setting fillStyle to a list item not working? - javascript

I'm making a drawing program, and it includes a tool that will change the color. It works using two lists, one that has the names of the CSS colors that I chose to represent he colors of the rainbow and black, and the other for the element that displays which color is selected, then I use a function that increments the value of a variable called selector, and and it all works mostly well. The text changes, but the color of the drawing doesn't. I have tried using the array that I'm putting in the fillStyle element in the innerText to see if that array is actually changing, and it is, the fillStyle just isn't changing. Any idea what's wrong? This is my code.
<canvas id='dr' width = '640' height = '480' style = 'display: block;' ></canvas>
<p id = 'color'></p>
<script>
var canvas = document.getElementById('dr');
var ctx = canvas.getContext('2d');
var line = false
function drawType(){
if (line === true){
line = false;}
else{line = true;}
}
var drawing = false;
function Type(){}
//start the drawing if the mouse is down
canvas.addEventListener('mousedown', () => {
drawing = true;
})
//stop the drawing if the mouse is up
canvas.addEventListener('mouseup', () => {
drawing = false;
});
//add an event listener to the canvas for when the user moves the mouse over it and the mouse is down
var colors = ['DarkRed', 'DarkOrange', 'Gold', 'Green', 'MediumBlue', 'Indigo', 'Violet', 'Black']
var displayColors = ['r', 'Red', 'Orange', 'Yellow', 'Green', 'Blue', 'Indigo', 'Violet', 'Black']
var selector = 0
var color = document.getElementById('color')
var selectedColor = colors[selector]
var selectedColor = colors[selector]
function switchColor(){
if (selector < 8)
{selector = selector + 1; }
else{selector = 1;}
color.innerText = displayColors[selector]
selectedColor = colors[selector]
ctx.fillstyle = selectedColor;
}
canvas.addEventListener('mousemove', (event) => {
//if the drawing mode is true (if the mouse button is down)
if (drawing == true) {
//put the rectangle on the canvas at the coordinates of the mouse
ctx.fillRect(event.pageX, event.pageY, 4, 4)
}
}
);
function clean(){
var canvas = document.getElementById('dr');
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, 640, 480);
}
</script>
<button onclick = 'switchColor()'> Switch drawing color</button>

var canvas = document.getElementById('dr');
var ctx = canvas.getContext('2d');
var line = false
function drawType() {
if (line === true) {
line = false;
} else {
line = true;
}
}
var drawing = false;
function Type() {}
//start the drawing if the mouse is down
canvas.addEventListener('mousedown', () => {
drawing = true;
})
//stop the drawing if the mouse is up
canvas.addEventListener('mouseup', () => {
drawing = false;
});
//add an event listener to the canvas for when the user moves the mouse over it and the mouse is down
var colors = ['DarkRed', 'DarkOrange', 'Gold', 'Green', 'MediumBlue', 'Indigo', 'Violet', 'Black']
var displayColors = ['r', 'Red', 'Orange', 'Yellow', 'Green', 'Blue', 'Indigo', 'Violet', 'Black']
var selector = 0
var color = document.getElementById('color')
var selectedColor = colors[selector];
function switchColor() {
if (selector < 8) {
selector = selector + 1;
} else {
selector = 1;
}
color.innerText = displayColors[selector];
selectedColor = colors[selector];
ctx.fillStyle = colors[selector-1];
}
canvas.addEventListener('mousemove', (event) => {
//if the drawing mode is true (if the mouse button is down)
if (drawing == true) {
//put the rectangle on the canvas at the coordinates of the mouse
ctx.fillRect(event.pageX, event.pageY, 4, 4)
}
});
function clean() {
var canvas = document.getElementById('dr');
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, 640, 480);
}
<canvas id='dr' width='640' height='480' style='display: block;'></canvas>
<p id='color'></p>
<button onclick='switchColor()'> Switch drawing color</button>

Related

Setting background image and work on top of it

I am using the below HTML to draw paths using paper.js. On the background we want to set a background image.
I tried to set image 'room.jpeg' which is stored locally. It loads correctly but it is not in the background. As a result it gets removed when I try drawing the path. The image should fit in the browser window.
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.14/fabric.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.12.15/paper-full.js"></script>
<script type="text/paperscript" canvas="canvas">
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
var img1 = new Image();
//drawing of the test image - img1
img1.onload = function() {
//draw background image
ctx.drawImage(img1, 0, 0);
//draw a box over the top
ctx.fillStyle = "rgba(200, 0, 0, 0.5)";
ctx.fillRect(0, 0, 500, 500);
};
img1.src = 'https://i.imgur.com/6gU9m8O.png'; // 'room.jpeg'; amended for this demo
var path;
var currentPath = [];
var textItem = new PointText({
content: '',
point: new Point(20, 30),
fillColor: 'black',
});
function onMouseDown(event) {
// If we produced a path before, deselect it:
if (path) {
path.selected = false;
}
// Create a new path and set its stroke color to black:
path = new Path({
segments: [event.point],
strokeColor: 'black',
// Select the path, so we can see its segment points:
fullySelected: false
});
}
// While the user drags the mouse, points are added to the path
// at the position of the mouse:
function onMouseDrag(event) {
console.log('Capturing new path');
path.add(event.point);
var point = event.point;
currentPath.push(point.x + ', ' + point.y);
// Update the content of the text item to show how many
// segments it has:
textItem.content = '';
}
// When the mouse is released, we simplify the path:
function onMouseUp(event) {
var segmentCount = path.segments.length;
// console.log(currentPath.toString());
console.log('End');
var poi = prompt("Please enter your poi start and end");
console.log('Saving Paths' + poi + (currentPath.toString()));
// When the mouse is released, simplify it:
path.simplify(10);
// Select the path, so we can see its segments:
path.fullySelected = false;
var newSegmentCount = path.segments.length;
var difference = segmentCount - newSegmentCount;
var percentage = 100 - Math.round(newSegmentCount / segmentCount * 100);
textItem.content = '';
}
</script>
<canvas id="canvas" resize></canvas>
Using an img as background gives more trouble since you'll need to redraw/move it on every run.
I'd just use some css to set an background-image to the <canvas> itself:
canvas {
width: 100vw;
height: 100vh;
background-image: url('https://via.placeholder.com/500/FFFFF3?text=BG');
}
canvas {
width: 100vw;
height: 100vh;
background-image: url('https://via.placeholder.com/500/FFFFF3?text=BG');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.12.15/paper-full.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.12.15/paper-core.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.14/fabric.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="canvas" resize></canvas>
<script type="text/paperscript" canvas="canvas">
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
var path;
var currentPath = [];
var textItem = new PointText({
content: '',
point: new Point(20, 30),
fillColor: 'black',
});
function onMouseDown(event) {
// If we produced a path before, deselect it:
if (path) {
path.selected = false;
}
// Create a new path and set its stroke color to black:
path = new Path({
segments: [event.point],
strokeColor: 'black',
// Select the path, so we can see its segment points:
fullySelected: false
});
}
// While the user drags the mouse, points are added to the path
// at the position of the mouse:
function onMouseDrag(event) {
//console.log('Capturing new path');
path.add(event.point);
var point = event.point;
currentPath.push(point.x + ', ' + point.y);
// Update the content of the text item to show how many
// segments it has:
textItem.content = '';
}
// When the mouse is released, we simplify the path:
function onMouseUp(event) {
var segmentCount = path.segments.length;
// console.log(currentPath.toString());
// console.log('End');
var poi = prompt("Please enter your poi start and end");
console.log('Saving Paths' + poi + (currentPath.toString()));
// When the mouse is released, simplify it:
path.simplify(10);
// Select the path, so we can see its segments:
path.fullySelected = false;
var newSegmentCount = path.segments.length;
var difference = segmentCount - newSegmentCount;
var percentage = 100 - Math.round(newSegmentCount / segmentCount * 100);
textItem.content = '';
}
</script>

Check if object is painted

I'm trying to create a coloring game for kids using animate cc. I used the following code:
var drawingCanvas;
var oldPt;
var oldMidPt;
var color;
var stroke = 50;
var index;
var that = this;
this.colorArray = ["#FF0000", "#009900", "#FFFF00", "#0000FF", "#000000", "#FF00FF"];
function init() {
index = 0;
createjs.Touch.enable(stage);
drawingCanvas = new createjs.Shape();
stage.addEventListener("stagemousedown", handleMouseDown);
stage.addEventListener("stagemouseup", handleMouseUp);
that.obj1.addChild(drawingCanvas);
//that.obj1.update();
}
function handleMouseDown(event) {
color = that.colorArray[(index++) % that.colorArray.length];
oldPt = that.obj1.globalToLocal(stage.mouseX, stage.mouseY);
oldMidPt = oldPt.clone();
stage.addEventListener("stagemousemove", handleMouseMove);
}
function handleMouseMove(event) {
var midPt = that.obj1.globalToLocal(stage.mouseX, stage.mouseY);
drawingCanvas.graphics.setStrokeStyle(stroke, 'round', 'round').beginStroke(color).moveTo(midPt.x, midPt.y).curveTo(oldPt.x, oldPt.y, oldMidPt.x,
oldMidPt.y);
oldPt.x = midPt.x;
oldPt.y = midPt.y;
oldMidPt.x = midPt.x;
oldMidPt.y = midPt.y;
//stage.update();
}
function handleMouseUp(event) {
stage.removeEventListener("stagemousemove", handleMouseMove);
}
init();
There is a movieclip where color will be applied and another movie clip above that which is just outline of the object. My question is, is it possible to check if the object is fully colored? Or is there any way to get the shape's color?

How can I stop draw with HTML5 Canvas

I'm trying to do my Paint-like using HTML 5 Canvas. I have to do two type of rectangle: filled and not filled. Here's how I did that:
function rectangle(state = false) {
var first = [];
var second = [];
var click = 0;
canvas.mousedown(function(e) {
if (status == "rectangle") {
if (click == 0) {
first[0] = e.offsetX;
first[1] = e.offsetY;
click++;
} else {
second[0] = e.offsetX;
second[1] = e.offsetY;
if (state) {
ctx.fillRect(
first[0],
first[1],
second[0] - first[0],
second[1] - first[1]
);
} else {
ctx = canvas[0].getContext("2d");
ctx.strokeRect(
first[0],
first[1],
second[0] - first[0],
second[1] - first[1]
);
}
click = 0;
}
}
});
}
and this is my call
//rectangle ;)
$("#fill").click(function() {
$("#alert").text("fill Rectangle");
status = "rectangle";
rectangle(true);
});
$("#contour").click(function() {
$("#alert").text("Rectangle");
status = "rectangle";
rectangle();
});
I have 2 buttons for choosing which type of rectangle the user wants.
When I click on filled I can draw my rectangle like I want but when I switch to not filled, it still draws by filling the rectangle. For drawing a not filled rectangle I have to press F5 and click first in not filled.
Your problem is you're adding a new event listener each time the fill checkbox is modified, but not removing the old listener. This means you're drawing both the outline-rect and the filled-rect. Instead, only add a single event listener and handle state indide it.
Additional notes:
Firstly, you don't have to recreate a new context each click.
Secondly, you have a lot of repeated code
Thirdly, use {x, y} instead of [x, y] for future ease of modification.
let shape = 'rectangle'
let fill = false;
let clicks = [], clickCount = 0;
let fillCheck = document.querySelector('input');
fillCheck.addEventListener('input', () => fill = fillCheck.checked);
let canvas = document.querySelector('canvas');
let ctx = canvas.getContext("2d");
canvas.addEventListener('mousedown', e => {
if (shape == 'rectangle') {
clicks[clickCount++] = {x: e.offsetX, y: e.offsetY};
if (clickCount === 2) {
ctx[fill ? 'fillRect' : 'strokeRect'](
clicks[0].x,
clicks[0].y,
clicks[1].x - clicks[0].x,
clicks[1].y - clicks[0].y);
clickCount = 0;
}
}
});
canvas {
outline: 1px solid;
}
<div><label><input type="checkbox">Fill?</label></div>
<canvas width="300" height="300"></canvas>

Is it possible to get strokes from a canvas with Javascript?

I'm using this drawing app: http://intridea.github.io/sketch.js/
I'm trying to get the stroke 'content' with: var ctx = colors_sketch.getContext("2d");
I'm looking for something that enables me to capture and redraw the canvas context. Like this:
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.moveTo(20,20);
// ... lots of lineTo's etc ...
ctx.lineTo(70,100);
ctx.strokeStyle="red";
ctx.stroke();
You can create a custom wrapper, and call its api to store the drawing operations in array, and when you done, use its api to stroke on canvas.
The wrapper would become mor complex than the snippet if you also intend to wrap other drawing operations like arcTo, bezierCurveTo, rect ... etc. But idea remains the same: Save the operations to a store with specific format, then when you're about to draw them on canvas, use ctx operations to replay those operations.
var StokeStore = function() {
this.store = [];
this.current = [];
}
StokeStore.prototype.moveTo = function(x, y) {
if (this.current.length !== 0) {
this.store.push(this.current);
this.current = [];
}
this.current.push({x: x, y: y});
};
StokeStore.prototype.lineTo = function(x, y) {
this.current.push({x: x, y: y});
};
StokeStore.prototype.stroke = function(ctx, style) {
ctx.beginPath();
ctx.strokeStyle = style ? style : 'black';
this.store.forEach(function(line) {
this._stroke(line);
}, this);
this._stroke(this.current);
ctx.stroke();
};
StokeStore.prototype._stroke = function(line) {
var length = line.length;
if (length < 2) {
return;
}
ctx.moveTo(line[0].x, line[0].y);
var index, pt;
for (index = 1; index < length; ++index) {
pt = line[index];
ctx.lineTo(pt.x, pt.y);
}
};
var canvas = document.getElementById('test');
var ctx = canvas.getContext('2d');
var print = document.getElementById('print');
var clear = document.getElementById('clear');
var exampleStroke = new StokeStore();
exampleStroke.moveTo(50, 50);
exampleStroke.lineTo(70, 70);
exampleStroke.lineTo(200, 50);
exampleStroke.lineTo(200, 190);
exampleStroke.moveTo(30, 90);
exampleStroke.lineTo(0, 290);
exampleStroke.lineTo(290, 40);
exampleStroke.lineTo(150, 150);
var randomColor = ['red', 'cyan', 'black', 'purple'];
print.addEventListener('click', function() {
var rnd = Math.floor(Math.random() * randomColor.length);
var style = randomColor[rnd];
exampleStroke.stroke(ctx, style);
});
clear.addEventListener('click', function() {
canvas.width = canvas.width;
});
<canvas id="test" width="300" height="300"></canvas>
<button id="print">print</button>
<button id="clear">clear</button>
Update to markE's comment:
I'm not good at modifying jQuery plugins, but it seems sketch.js do provide a storage itself, when you call its api, it sets data-sketch attribute to store its created instance, so you can try to interact with that instance, like its redraw or else.
Also, it use a similar format to store the sketch history, if we use var sketch = $(CANVAS).data('sketch') to get the instance, we can use sketch.actions to get all stroke, and each stroke has an array called events, which stores Objects with attribute x, y, eventType, so if you want, you can either retrieve the strokes from it, or put your own stroke into the history. Like:
sketch.actions.push({
color: //stroke color,
size: // stroke size,
tool: // marker will draw, while eraser will erase to white,
events: [
{x:xval, y:yval, event:evType},....
]
});
jsfiddle or snippet below.
$(function() {
var $cv = $('#test');
var cv = $cv.get(0);
$('#test').sketch();
var sketch = $cv.data('sketch');
$('#clear').click(function() {
cv.width = cv.width;
});
$('#redraw').click(function() {
sketch.redraw();
});
$('#strokes').click(function() {
var $display = $('#display').empty();
sketch.actions.forEach(function(strk, idx) {
if (!strk.events) {
return;
}
var $div = $('<div>').addClass('stroke');
$('<div>').text('Stroke #' + idx).appendTo($div);
strk.events.forEach(function(pt, idx) {
$("<p>").text(idx + ': (' + pt.x + ',' + pt.y + ')' ).appendTo($div);
});
$div.appendTo($display);
});
});
});
#test {
border: solid 1px gray;
}
.stroke {
border: solid 1px blue;
float : left;
padding: 10px;
margin: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://rawgit.com/intridea/sketch.js/master/lib/sketch.min.js"></script>
<canvas id="test" width="500" height="500;"></canvas>
<button id="clear">clear</button>
<button id="redraw">redraw</button>
<button id="strokes">print strokes</button>
<div id="display"></div>

Drawing lines along the cursor path in KineticJS

I am using KineticJS to implement a drawing application. I have used it to draw shapes, straight lines. I have used way described in KineticJS - Drawing Lines with Mouse to draw straight lines. But now my requirement is to draw line along the mouse path! What should be the procedure for that? Can we use Kinetic.Path to do that?
Following code is used to draw straight lines,
var Object,startingPoint;
var down = false;
layer.on("mousedown", function(e) {
down = true;
Object = new Kinetic.Line({
points: [e.layerX, e.layerY,e.layerX+1, e.layerY+1],
stroke: "red"
});
layer.add(Object);
});
layer.on("mousemove", function(e) {
if (down) {
var x = e.layerX;
var y = e.layerY;
Object.getPoints()[1].x = e.layerX;
Object.getPoints()[1].y = e.layerY;
down = true;
layer.draw();
}
});
layer.on("mouseup", function(e) {
down = false;
});
I have replaced Kinetic.Line with Kinetic.Path to achieve the target. But it didn't work.
if you need to add points to a line you can do this:
var points = line.getPoints();
var pos = stage.getUserPosition();
points = points.push(pos.x, pos.y);
line.setPoints(points);
Here how I implemented it. The key is to use spline shape of kineticJS and push points in it during mousemove and mouseup. ev._x, ev._y are the x, and y points calculated in the light of this post
Tracking mouse position in canvas when no surrounding element exists
Please let me know if it helps
tools.pencil = function () {
var tool = this;
this.started = false;
var drawObject;
this.mousedown = function (ev) {
drawObject = new DrawObject();
drawObject.Tool = DrawTool.Pencil;
tool.started = true;
drawObject.currentState = DrawState.Started;
drawObject.StartX = ev._x;
drawObject.StartY = ev._y;
tool.DrawIt(drawObject);
};
this.mousemove = function (ev) {
if (tool.started) {
drawObject.currentState = DrawState.Inprogress;
drawObject.CurrentX = ev._x;
drawObject.CurrentY = ev._y;
tool.DrawIt(drawObject);
};
this.mouseup = function (ev) {
if (tool.started) {
tool.started = false;
drawObject.currentState = DrawState.Completed;
drawObject.CurrentX = ev._x;
drawObject.CurrentY = ev._y;
tool.DrawIt(drawObject);
}
};
this.mouseout = function (ev) {
if (tool.started) {
}
tool.started = false;
};
this.DrawIt = function (drawObject) {
switch (drawObject.currentState) {
case DrawState.Started:
var x= drawObject.StartX,
y = drawObject.StartY;
var pencil = new Kinetic.Spline({
points: [{
x: x,
y: y
}],
stroke: 'red',
strokeWidth: 2,
lineCap: 'round',
tension: 1,
name: shapes.length
});
drawObject.Shape = pencil;
layer.add(pencil);
layer.draw();
break;
case DrawState.Inprogress:
case DrawState.Completed:
var x = drawObject.CurrentX,
y = drawObject.CurrentY;
var pencil = drawObject.Shape;
pencil.attrs.points.push({ x: x, y: y });
pencil.setPoints(pencil.attrs.points);
layer.draw();
if (drawObject.currentState == DrawState.Completed) {
// dosomething
}
break;
}
Where draw object is simple empty function in javascript
function DrawObject()
{
}
and drawstate is all the available state of pencil tool
var DrawState =
{
Started: 0,
Inprogress: 1,
Completed: 2
}
and "layer" is simple KineticJS layer already added in KineticJS stage

Categories

Resources