pixel-editor/js/_mouseEvents.js

448 lines
16 KiB
JavaScript
Raw Normal View History

var currentMouseEvent;
var lastMouseMovePos;
2019-03-27 02:20:54 +03:00
//mousedown - start drawing
window.addEventListener("mousedown", function (mouseEvent) {
// Saving the event in case something else needs it
currentMouseEvent = mouseEvent;
2020-04-04 16:56:44 +03:00
canDraw = true;
//if no document has been created yet, or this is a dialog open, or the currentLayer is locked
if (!documentCreated || Dialogue.isOpen() || currentLayer.isLocked || !currentLayer.isVisible) return;
2019-03-27 02:20:54 +03:00
//prevent right mouse clicks and such, which will open unwanted menus
//mouseEvent.preventDefault();
lastMouseClickPos = getCursorPosition(mouseEvent);
2019-03-27 02:20:54 +03:00
dragging = true;
2020-03-07 18:49:01 +03:00
//left or right click ?
2019-03-27 02:20:54 +03:00
if (mouseEvent.which == 1) {
if (spacePressed)
currentTool = tool.pan;
else if (mouseEvent.altKey)
currentTool = tool.eyedropper;
else if (mouseEvent.target.className == 'drawingCanvas' &&
(currentTool.name == 'pencil' || currentTool.name == 'eraser' || currentTool.name == 'rectangle' || currentTool.name == 'ellipse' || currentTool.name === 'line'))
new HistoryState().EditCanvas();
else if (currentTool.name == 'moveselection') {
if (!cursorInSelectedArea() &&
((mouseEvent.target.id == 'canvas-view') || mouseEvent.target.className == 'drawingCanvas')) {
tool.pencil.switchTo();
2020-04-04 16:56:44 +03:00
canDraw = false;
2020-03-15 19:11:00 +03:00
}
}
if (!currentLayer.isLocked && !currentLayer.isVisible && canDraw) {
2020-04-04 16:56:44 +03:00
draw(mouseEvent);
}
2019-03-27 02:20:54 +03:00
}
2021-06-25 23:42:00 +03:00
else if (mouseEvent.which == 2) {
currentTool = tool.pan;
}
else if (currentTool.name == 'pencil' && mouseEvent.which == 3) {
currentTool = tool.resizebrush;
tool.pencil.previousBrushSize = tool.pencil.brushSize;
2019-03-27 02:20:54 +03:00
}
else if (currentTool.name == 'eraser' && mouseEvent.which == 3) {
currentTool = tool.resizeeraser;
tool.eraser.previousBrushSize = tool.eraser.brushSize;
}
// TODO: [ELLIPSE] Do we need similar logic related to ellipse?
else if (currentTool.name == 'rectangle' && mouseEvent.which == 3) {
currentTool = tool.resizerectangle;
tool.rectangle.previousBrushSize = tool.rectangle.brushSize;
2020-03-07 18:49:01 +03:00
}
2021-01-14 23:28:57 +03:00
else if (currentTool.name == 'line' && mouseEvent.which == 3) {
currentTool = tool.resizeline;
tool.line.previousBrushSize = tool.line.brushSize;
}
2020-03-07 18:49:01 +03:00
if (currentTool.name == 'eyedropper' && mouseEvent.target.className == 'drawingCanvas')
2019-03-27 02:20:54 +03:00
eyedropperPreview.style.display = 'block';
2019-03-27 02:20:54 +03:00
return false;
}, false);
//mouseup - end drawing
window.addEventListener("mouseup", function (mouseEvent) {
// Saving the event in case something else needs it
currentMouseEvent = mouseEvent;
TopMenuModule.closeMenu();
if (currentLayer != null && !Util.isChildOfByClass(mouseEvent.target, "layers-menu-entry")) {
currentLayer.closeOptionsMenu();
}
2021-01-14 23:28:57 +03:00
// If the user finished placing down a line, clear the tmp canvas and copy the data to the current layer
if (currentTool.name === "line") {
const tmpCanvas = document.getElementById('tmp-canvas');
currentLayer.context.drawImage(tmpCanvas, 0, 0);
const tmpContext = tmpCanvas.getContext('2d');
tmpContext.clearRect(0, 0, tmpCanvas.width, tmpCanvas.height);
}
2021-07-15 00:00:12 +03:00
if (!documentCreated || Dialogue.isOpen() || !currentLayer.isVisible || currentLayer.isLocked) return;
if (currentTool.name == 'eyedropper' && mouseEvent.target.className == 'drawingCanvas') {
2019-03-27 02:20:54 +03:00
var cursorLocation = getCursorPosition(mouseEvent);
var selectedColor = getEyedropperColor(cursorLocation);
2021-07-11 18:32:49 +03:00
const rgbColor = {r:selectedColor[0],g:selectedColor[1],b:selectedColor[2]};
var newColor = Color.rgbToHex(rgbColor);
currentGlobalColor = "#" + newColor;
for (let i=1; i<layers.length - 1; i++) {
layers[i].context.fillStyle = currentGlobalColor;
}
2019-03-27 02:20:54 +03:00
var colors = document.getElementsByClassName('color-button');
for (var i = 0; i < colors.length; i++) {
//if picked color matches this color
if (newColor == colors[i].jscolor.toString()) {
//remove current color selection
var selectedColor = document.querySelector("#colors-menu li.selected")
if (selectedColor) selectedColor.classList.remove("selected");
//set current color
for (let i=2; i<layers.length; i++) {
layers[i].context.fillStyle = '#' + newColor;
}
//make color selected
colors[i].parentElement.classList.add('selected');
//hide eyedropper
eyedropperPreview.style.display = 'none';
}
}
2019-03-27 02:20:54 +03:00
}
else if (currentTool.name == 'fill' && mouseEvent.target.className == 'drawingCanvas') {
2019-03-27 02:20:54 +03:00
//get cursor postion
var cursorLocation = getCursorPosition(mouseEvent);
2019-03-27 02:20:54 +03:00
//offset to match cursor point
cursorLocation[0] += 2;
cursorLocation[1] += 12;
//fill starting at the location
2019-03-27 02:20:54 +03:00
fill(cursorLocation);
currentLayer.updateLayerPreview();
2019-03-27 02:20:54 +03:00
}
else if (currentTool.name == 'zoom' && mouseEvent.target.className == 'drawingCanvas') {
let mode;
if (mouseEvent.which == 1){
mode = "in";
}
2020-04-04 10:41:56 +03:00
}
else if (currentTool == 'zoom' && mouseEvent.target.className == 'drawingCanvas') {
let mode;
if (mouseEvent.which == 1){
mode = 'in';
}
else if (mouseEvent.which == 3){
mode = 'out';
}
2020-12-31 15:05:51 +03:00
changeZoom(mode, getCursorPosition(mouseEvent));
for (let i=1; i<layers.length; i++) {
2020-04-04 10:41:56 +03:00
layers[i].copyData(layers[0]);
}
2019-03-27 02:20:54 +03:00
}
else if (currentTool.name == 'rectselect' && isRectSelecting) {
endRectSelection(mouseEvent);
}
else if (currentTool.name == 'rectangle' && isDrawingRect) {
endRectDrawing(mouseEvent);
currentLayer.updateLayerPreview();
}
else if (currentTool.name == 'ellipse' && isDrawingEllipse) {
endEllipseDrawing(mouseEvent);
currentLayer.updateLayerPreview();
}
2019-03-27 02:20:54 +03:00
dragging = false;
currentTool = currentToolTemp;
currentTool.updateCursor();
2019-03-27 02:20:54 +03:00
}, false);
2020-09-17 17:11:00 +03:00
function setPreviewPosition(preview, size){
let toAdd = 0;
// This prevents the brush to be placed in the middle of pixels
if (size % 2 == 0) {
toAdd = 0.5;
}
2020-04-04 21:48:54 +03:00
preview.style.left = (
currentLayer.canvas.offsetLeft
+ Math.floor(cursor[0]/zoom) * zoom
2020-09-17 17:11:00 +03:00
- Math.floor(size / 2) * zoom + toAdd
2020-04-04 21:48:54 +03:00
) + 'px';
preview.style.top = (
currentLayer.canvas.offsetTop
+ Math.floor(cursor[1]/zoom) * zoom
2020-09-17 17:11:00 +03:00
- Math.floor(size / 2) * zoom + toAdd
2020-04-04 21:48:54 +03:00
) + 'px';
}
2019-03-27 02:20:54 +03:00
// OPTIMIZABLE: redundant || mouseEvent.target.className in currentTool ifs
//mouse is moving on canvas
2019-03-27 02:20:54 +03:00
window.addEventListener("mousemove", draw, false);
window.addEventListener("mousedown", draw, false);
2019-03-27 02:20:54 +03:00
function draw (mouseEvent) {
if (!Dialogue.isOpen())
2020-09-16 13:43:51 +03:00
{
lastMouseMovePos = getCursorPosition(mouseEvent);
// Saving the event in case something else needs it
currentMouseEvent = mouseEvent;
var cursorLocation = lastMouseMovePos;
//if a document hasnt yet been created or the current layer is locked, exit this function
2021-07-15 00:00:12 +03:00
if (!documentCreated || Dialogue.isOpen() || !currentLayer.isVisible || currentLayer.isLocked) return;
2020-09-16 13:43:51 +03:00
// Moving brush preview
currentTool.moveBrushPreview(cursorLocation);
// Hiding eyedropper, will be shown if it's needed
eyedropperPreview.style.display = 'none';
if (currentTool.name == 'pencil') {
//hide brush preview outside of canvas / canvas view
if (mouseEvent.target.className == 'drawingCanvas'|| mouseEvent.target.className == 'drawingCanvas')
brushPreview.style.visibility = 'visible';
else
brushPreview.style.visibility = 'hidden';
//draw line to current pixel
if (dragging) {
if (mouseEvent.target.className == 'drawingCanvas' || mouseEvent.target.className == 'drawingCanvas') {
line(Math.floor(lastMouseClickPos[0]/zoom),
Math.floor(lastMouseClickPos[1]/zoom),
Math.floor(cursorLocation[0]/zoom),
Math.floor(cursorLocation[1]/zoom),
tool.pencil.brushSize
);
2020-09-16 13:43:51 +03:00
lastMouseClickPos = cursorLocation;
}
2019-03-27 02:20:54 +03:00
}
2020-09-16 13:43:51 +03:00
//get lightness value of color
var selectedColor = currentLayer.context.getImageData(Math.floor(cursorLocation[0]/zoom),Math.floor(cursorLocation[1]/zoom),1,1).data;
var colorLightness = Math.max(selectedColor[0],selectedColor[1],selectedColor[2])
//for the darkest 75% of colors, change the brush preview to dark mode
if (colorLightness>64) brushPreview.classList.remove('dark');
2020-09-16 13:43:51 +03:00
else brushPreview.classList.add('dark');
2020-09-16 13:43:51 +03:00
currentLayer.updateLayerPreview();
}
// Decided to write a different implementation in case of differences between the brush and the eraser tool
else if (currentTool.name == 'eraser') {
//hide brush preview outside of canvas / canvas view
if (mouseEvent.target.className == 'drawingCanvas' || mouseEvent.target.className == 'drawingCanvas')
brushPreview.style.visibility = 'visible';
else
brushPreview.style.visibility = 'hidden';
//draw line to current pixel
if (dragging) {
if (mouseEvent.target.className == 'drawingCanvas' || mouseEvent.target.className == 'drawingCanvas') {
line(Math.floor(lastMouseClickPos[0]/zoom),Math.floor(lastMouseClickPos[1]/zoom),Math.floor(cursorLocation[0]/zoom),Math.floor(cursorLocation[1]/zoom), currentTool.brushSize);
lastMouseClickPos = cursorLocation;
}
}
2020-09-16 13:43:51 +03:00
currentLayer.updateLayerPreview();
}
2020-09-16 13:43:51 +03:00
else if (currentTool.name == 'rectangle')
{
//hide brush preview outside of canvas / canvas view
if (mouseEvent.target.className == 'drawingCanvas'|| mouseEvent.target.className == 'drawingCanvas')
brushPreview.style.visibility = 'visible';
else
brushPreview.style.visibility = 'hidden';
if (!isDrawingRect && dragging) {
startRectDrawing(mouseEvent);
}
else if (dragging){
updateRectDrawing(mouseEvent);
}
}
else if (currentTool.name == 'ellipse')
{
//hide brush preview outside of canvas / canvas view
if (mouseEvent.target.className == 'drawingCanvas'|| mouseEvent.target.className == 'drawingCanvas')
brushPreview.style.visibility = 'visible';
else
brushPreview.style.visibility = 'hidden';
if (!isDrawingEllipse && dragging) {
startEllipseDrawing(mouseEvent);
}
else if (dragging){
updateEllipseDrawing(mouseEvent);
}
}
2020-09-16 13:43:51 +03:00
else if (currentTool.name == 'pan' && dragging) {
// Setting first layer position
layers[0].setCanvasOffset(layers[0].canvas.offsetLeft + (cursorLocation[0] - lastMouseClickPos[0]), layers[0].canvas.offsetTop + (cursorLocation[1] - lastMouseClickPos[1]));
2020-09-16 13:43:51 +03:00
// Copying that position to the other layers
for (let i=1; i<layers.length; i++) {
layers[i].copyData(layers[0]);
}
}
else if (currentTool.name == 'eyedropper' && dragging && mouseEvent.target.className == 'drawingCanvas') {
2021-07-11 18:32:49 +03:00
const selectedColor = getEyedropperColor(cursorLocation);
const rgbColor = {r:selectedColor[0],g:selectedColor[1],b:selectedColor[2]};
eyedropperPreview.style.borderColor = '#' + Color.rgbToHex(rgbColor);
2020-09-16 13:43:51 +03:00
eyedropperPreview.style.display = 'block';
2020-09-16 13:43:51 +03:00
eyedropperPreview.style.left = cursorLocation[0] + currentLayer.canvas.offsetLeft - 30 + 'px';
eyedropperPreview.style.top = cursorLocation[1] + currentLayer.canvas.offsetTop - 30 + 'px';
2021-07-11 18:32:49 +03:00
const colorLightness = Math.max(selectedColor[0],selectedColor[1],selectedColor[2]);
2020-09-16 13:43:51 +03:00
//for the darkest 50% of colors, change the eyedropper preview to dark mode
if (colorLightness>127) eyedropperPreview.classList.remove('dark');
else eyedropperPreview.classList.add('dark');
}
else if (currentTool.name == 'resizebrush' && dragging) {
//get new brush size based on x distance from original clicking location
var distanceFromClick = cursorLocation[0] - lastMouseClickPos[0];
//var roundingAmount = 20 - Math.round(distanceFromClick/10);
//this doesnt work in reverse... because... it's not basing it off of the brush size which it should be
var brushSizeChange = Math.round(distanceFromClick/10);
var newBrushSize = tool.pencil.previousBrushSize + brushSizeChange;
//set the brush to the new size as long as its bigger than 1
tool.pencil.brushSize = Math.max(1,newBrushSize);
//fix offset so the cursor stays centered
tool.pencil.moveBrushPreview(lastMouseClickPos);
currentTool.updateCursor();
}
else if (currentTool.name == 'resizeeraser' && dragging) {
//get new brush size based on x distance from original clicking location
var distanceFromClick = cursorLocation[0] - lastMouseClickPos[0];
//var roundingAmount = 20 - Math.round(distanceFromClick/10);
//this doesnt work in reverse... because... it's not basing it off of the brush size which it should be
var eraserSizeChange = Math.round(distanceFromClick/10);
var newEraserSizeChange = tool.eraser.previousBrushSize + eraserSizeChange;
//set the brush to the new size as long as its bigger than 1
tool.eraser.brushSize = Math.max(1,newEraserSizeChange);
//fix offset so the cursor stays centered
tool.eraser.moveBrushPreview(lastMouseClickPos);
currentTool.updateCursor();
}
else if (currentTool.name == 'resizerectangle' && dragging) {
//get new brush size based on x distance from original clicking location
var distanceFromClick = cursorLocation[0] - lastMouseClickPos[0];
//var roundingAmount = 20 - Math.round(distanceFromClick/10);
//this doesnt work in reverse... because... it's not basing it off of the brush size which it should be
var rectangleSizeChange = Math.round(distanceFromClick/10);
// TODO: [ELLIPSE] Do we need similar logic related to ellipse?
2020-09-16 13:43:51 +03:00
var newRectangleSize = tool.rectangle.previousBrushSize + rectangleSizeChange;
//set the brush to the new size as long as its bigger than 1
// TODO: [ELLIPSE] Do we need similar logic related to ellipse?
2020-09-16 13:43:51 +03:00
tool.rectangle.brushSize = Math.max(1,newRectangleSize);
//fix offset so the cursor stays centered
// TODO: [ELLIPSE] Do we need similar logic related to ellipse?
2020-09-16 13:43:51 +03:00
tool.rectangle.moveBrushPreview(lastMouseClickPos);
currentTool.updateCursor();
}
2021-01-15 03:50:56 +03:00
else if (currentTool.name == 'resizeline' && dragging) {
//get new brush size based on x distance from original clicking location
var distanceFromClick = cursorLocation[0] - lastMouseClickPos[0];
//var roundingAmount = 20 - Math.round(distanceFromClick/10);
//this doesnt work in reverse... because... it's not basing it off of the brush size which it should be
var lineSizeChange = Math.round(distanceFromClick/10);
var newLineSize = tool.line.previousBrushSize + lineSizeChange;
//set the brush to the new size as long as its bigger than 1
tool.line.brushSize = Math.max(1, newLineSize);
//fix offset so the cursor stays centered
tool.line.moveBrushPreview(lastMouseClickPos);
currentTool.updateCursor();
}
2020-09-16 13:43:51 +03:00
else if (currentTool.name == 'rectselect') {
if (dragging && !isRectSelecting && mouseEvent.target.className == 'drawingCanvas') {
isRectSelecting = true;
startRectSelection(mouseEvent);
}
else if (dragging && isRectSelecting) {
updateRectSelection(mouseEvent);
}
else if (isRectSelecting) {
endRectSelection();
}
}
else if (currentTool.name == 'moveselection') {
// Updating the cursor (move if inside rect, cross if not)
currentTool.updateCursor();
2020-03-05 18:13:23 +03:00
2020-09-16 13:43:51 +03:00
// If I'm dragging, I move the preview
if (dragging && cursorInSelectedArea()) {
updateMovePreview(getCursorPosition(mouseEvent));
}
}
2021-01-14 21:04:39 +03:00
else if (currentTool.name === "line") {
2021-01-14 23:28:57 +03:00
if (mouseEvent.target.className == 'drawingCanvas'|| mouseEvent.target.className == 'drawingCanvas') {
brushPreview.style.visibility = 'visible';
} else {
brushPreview.style.visibility = 'hidden';
}
2021-01-14 21:04:39 +03:00
if (dragging) {
if (mouseEvent.target.className == 'drawingCanvas' || mouseEvent.target.className == 'drawingCanvas') {
diagLine(lastMouseClickPos, zoom, cursorLocation);
}
}
currentLayer.updateLayerPreview();
}
2020-09-16 13:43:51 +03:00
}
if (mouseEvent.target.className == 'drawingCanvas')
currentTool.updateCursor();
else
canvasView.style.cursor = 'default';
2019-03-27 02:20:54 +03:00
}
//mousewheel scroll
2019-03-27 02:20:54 +03:00
canvasView.addEventListener("wheel", function(mouseEvent){
let mode;
if (mouseEvent.deltaY < 0){
mode = 'in';
}
else if (mouseEvent.deltaY > 0) {
mode = 'out';
}
// Changing zoom and position of the first layer
2020-12-31 15:05:51 +03:00
changeZoom(mode, getCursorPosition(mouseEvent));
for (let i=1; i<layers.length; i++) {
// Copying first layer's data into the other layers
layers[i].copyData(layers[0]);
2019-03-27 02:20:54 +03:00
}
});