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
Related
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?
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>
I'm trying to make a simple graphics program for doodling and such, but I'm having some trouble with the line tools provided by PIXI.Graphics().
I draw lines by using events such as pointerdown, pointermove, etc. Saving the last coordinate and then using moveTo and lineTo to draw a continuous line until you trigger pointerup. When drawing a line however gaps appear in semi-regular intervals.
Those gaps are always in the color used in the beginFill() fill statement. Even if I use multiple colors, they will appear in the line, making it not really "gaps" but wrongly colored lines.
When a long line is drawn via code, the same error does not seem to occur.
I'm quite stumped by the behaviour and it would be nice if you could help me out!
Here is the code I used:
let app;
let graphics;
var isDrawing = false;
var x = 0;
var y = 0;
var count = 0;
window.onload = function(){
var canvasContainer = document.getElementById("areaCanvasContainer");
//Create a Pixi Application
app = new PIXI.Application({
width: 600,
height: 500,
antialias: false,
transparent: false,
resolution: 1,
forceCanvas: false,
backgroundColor: 0xFFFFFF
});
canvasContainer.appendChild(app.view);
graphics = new PIXI.Graphics();
graphics.interactive = true;
graphics.buttonMode = true;
graphics.beginFill(0xFFFFFF);
graphics.drawRect(0, 0, 600, 500);
graphics.endFill();
graphics.lineStyle(3, 0x000000,1.0,0.5,false);
graphics.on("pointerdown", mousedown);
graphics.on("pointermove", mousemove);
graphics.on("pointerup", mouseup);
graphics.on("pointerupoutside", mouseup);
app.stage.addChild(graphics);
}
function mousedown(e) {
x = e.data.global.x;
y = e.data.global.y;
isDrawing = true;
}
function mousemove(e) {
if (isDrawing === true) {
if(Math.abs(x - e.data.global.x) > 2 || Math.abs(y - e.data.global.y ) > 2 ){
drawLine(graphics, x, y, e.data.global.x, e.data.global.y);
x = e.data.global.x;
y = e.data.global.y;
}
}
}
function mouseup(e) {
if (isDrawing === true) {
drawLine(graphics, x, y, e.data.global.x, e.data.global.y);
x = 0;
y = 0;
isDrawing = false;
}
}
function drawLine(graphics, x1, y1, x2, y2) {
if(!(x1 === x2 && y1 === y2)){
graphics.endFill();
graphics.moveTo(x1, y1);
graphics.lineTo(x2, y2);
}
}
I have a problem with an application that would allow people to draw lines on the same canvas. Currently, my application only work locally. When I have multiple pages opened, the application works fine, the same drawing is on every canvas. However, when a page is reduced or opened in another tab, this page doesn't have the same canvas, most of the lines that should appear on this canvas are missing.
To reproduce the content of a canvas every time we add a line, I use the canvas method DrawImage().
Here is the code of the client side:
var url = 'http://localhost:4000';
var socket = io.connect(url);
var mouseData= {};
var startLine= false;
var first= {};
var last= {};
var tmpPosition= {};
var canvas = document.getElementById('tableauBlanc');
var contextCanvas1 = canvas.getContext('2d');
var Images = new Image();
var data;
canvas.addEventListener('mousemove', function(MouseEvent) {
tmpPosition=.x = MouseEvent.clientX;
tmpPosition=.y = MouseEvent.clientY;
tmpPosition== adaptMousePosition(tmpPosition=.x, tmpPosition=.y);
if (startLine) {
socket.emit('deleteAndRedrawCanvas', Images);
mouseData.px = first.x;
mouseData.py = first.y;
mouseData.dx = tmpPosition=.x;
mouseData.dy = tmpPosition=.y;
mouseData.validate= false;
socket.emit('DrawLine', mouseData);
}
}
});
canvas.addEventListener('click', function(MouseEvent) {
if (startDroite) {
last.x = MouseEvent.clientX;
last.y = MouseEvent.clientY;
last= adaptMousePosition(last.x, last.y);
contextCanvas1.strokeStyle = "#FF0000";
mouseData.px = first.x;
mouseData.py = first.y;
mouseData.dx = last.x;
mouseData.dy = last.y;
mouseData.validate= true;
socket.emit('DrawLine', mouseData);
startLine= false;
} else {
first.x = MouseEvent.clientX;
first.y = MouseEvent.clientY;
first= adaptMousePosition(first.x, first.y);
startLine= true;
}
});
socket.on('Draw', function(mouseData) {
contextCanvas1.strokeStyle = "#FF0000";
DrawLine(mouseData.px, mouseData.py, mouseData.dx, mouseData.dy);
if (mouseData.fini == true) {
setTimeout(DrawCanvas, 20);
}
});
function DrawCanvas() {
data = canvas.toDataURL();
Images.src = data;
Images.onload = function() {
Images.src = data;
contextCanvas1.drawImage(Images, 0, 0, 500, 500);
}
}
function DrawLine(px, py, dx, dy) {
contextCanvas1.strokeStyle = "#FF0000";
contextCanvas1.moveTo(px, py);
contextCanvas1.lineTo(dx, dy);
contextCanvas1.stroke();
}
socket.on('deleteAndRedrawCanvas', function(Images) {
contextCanvas1.clearRect(0, 0, 500, 500);
contextCanvas1.beginPath();
});
function adaptMousePosition(posX, posY) {
var gap= canvas.getBoundingClientRect();
return {
x: posX - gap.left,
y: posY - gap.top
};
}
Thanks for any pieces of advice.
By the way, that's the first time that I'm using Javascript and NodeJS, my code may be badly structured.
I am building a tower defence game and I am facing an issue in Phaser with tiled maps.
You see different layers in tiled always have coordinates from (0,0) to (600,600) -> or whatever your tiled width and height is. I have a backgroundLayer and a path. The creeps properly collide with the path.
Now I am trying to change the cursor to a building sprite (for UI when I click on some button and select a tower I want it to turn red when it is on the road or above another tower/creep) and I am using an overlap function for path and buildings.
This overlap function in Phaser checks the rectangle of building sprite and path, but path rectangle is the whole map. The collision works but I only need an overlap. Any ideas how to achieve this? Here is my code.
var RedPlanetGame = RedPlanetGame || {};
var pressed = {
is: false
};
var buildingOverlaps = {
is: false
};
//title screen
RedPlanetGame.Game = function () {
};
RedPlanetGame.Game.prototype = {
create: function create() {
//A door for multyplayer
this.players = [];
this.player = new Player(1, 'Daniel', 300);
this.players.push(this.player);
this.playerInfo = {};
//Tile map
this.map = this.game.add.tilemap('sample2');
this.map.addTilesetImage('32x32_map_tile v3.1 [MARGINLESS]', 'gameTiles');
//background and layers
this.backgroundlayer = this.map.createLayer('backgroundLayer');
this.path = this.map.createLayer('path');
this.map.setCollisionBetween(1, 2000, true, 'backgroundLayer');
this.map.setCollisionBetween(1, 2000, true, 'path');
//objects from tile map
this.spawnCreepsAt = this.map.objects['objectsLayer'][0];
this.destinationForCreeps = this.map.objects['objectsLayer'][1];
//resize world
this.backgroundlayer.resizeWorld();
//this.game.world.setBounds(0, 0, 100, 100);
//groups
this.game.enemies = new UnitsPoolFactory(this.game);
this.game.buildings = this.game.add.group();//TODO: make buildings for each player
this.game.bullets = new BulletsPoolFactory(this.game);
//creep spawning
var _this = this;
const creepYOffset = 15;
setInterval(function () {
_this.game.enemies.factory(_this.spawnCreepsAt.x, _this.spawnCreepsAt.y + creepYOffset, UNIT_TYPES.CREEP1);
}, 1000);
//text and player info
var textX = 150;
var textY = 0;
this.playerInfo.gold = this.game.add.text(textX, textY, 'Player gold: ' + this.player.gold,
{font: "24px Arial", fill: '#FFD700'}
);
//Here is test straight forward code for building towers
this.game.build = this.game.add.group();
this.buildingSprite = this.game.add.sprite(0, 0, 'tower1-1');
this.game.physics.enable(this.buildingSprite, Phaser.Physics.ARCADE);
this.buildingSprite.anchor.setTo(0.5);
this.buildingSprite.scale.setTo(0.5);
this.game.build.add(this.buildingSprite);
console.log(this.path.getBounds());
console.log(this.backgroundlayer.getBounds());
},
update: function update() {
var _this = this;
//Camera follow cursor
if (this.game.input.mousePointer.x > gameHeight - gameHeight / 10) {
this.game.camera.x += 10;
} else if (this.game.input.mousePointer.x <= 100) {
this.game.camera.x -= 10;
}
if (this.game.input.mousePointer.y > gameWidth - gameWidth / 10) {
this.game.camera.y += 10;
} else if (this.game.input.mousePointer.y <= 100) {
this.game.camera.y -= 10;
}
//check for collision between enemy and non-path layer
this.game.physics.arcade.collide(this.game.enemies, this.backgroundlayer);
//checks for collision between bullets and enemies
this.game.physics.arcade.overlap(this.game.bullets, this.game.enemies, function (bullet, enemy) {
enemy.takeHit(bullet, _this.player);
bullet.kill();
}, null, this);
//updates enemies
this.game.enemies.forEach(function (enemy) {
enemy.onUpdate(_this.destinationForCreeps);
});
//updates buildings
this.game.buildings.forEach(function (building) {
building.onUpdate(_this.game.bullets);
});
//on mouse down event
if (this.game.input.activePointer.leftButton.isDown && !pressed.is) {//yo Yoda
//builds new building of type TOWER1
buffer(pressed, 1000);
if (Building.prototype.canBuild(this.player.gold, Tower1.prototype.moneyCost)) {
var poss = this.game.input.mousePointer;
BuildingsFactory(this.game, poss.x, poss.y, this.player, BUILDING_TYPES.TOWER1);
this.player.gold -= Tower1.prototype.moneyCost
} else {
alert('Not enought gold');
}
}
//Here is test straight forward code for building towers
if (Phaser.Rectangle.contains(this.buildingSprite.body, this.game.input.x, this.game.input.y)) {
this.buildingSprite.body.velocity.setTo(0, 0);
}
else {
this.game.physics.arcade.moveToPointer(this.buildingSprite, 700);
}
this.game.physics.arcade.collideGroupVsTilemapLayer(this.game.build, this.path, function (sprite) {
if (!buildingOverlaps.is) {
buffer(buildingOverlaps, 500);
console.log('overlap')
}
}, null, this, true);
},
render: function render() {
this.playerInfo.gold.text = 'Player gold: ' + this.player.gold;
}
};