Added ellipse tool setup

This commit is contained in:
Nicola 2022-01-22 16:02:10 +01:00
parent 6900ecb0c0
commit 832f36992b
9 changed files with 168 additions and 179 deletions

View File

@ -28,12 +28,14 @@
z-index:0;
}
#tools-menu li button path {
#tools-menu li button path, #tools-menu li button ellipse {
fill: $baseicon;
stroke: $baseicon;
}
#tools-menu li:hover button:first-child path {
#tools-menu li:hover button:first-child path, #tools-menu li:hover button:first-child ellipse {
fill: $basehovericon;
stroke: $basehovericon;
}
@ -41,7 +43,7 @@
background: $baseselected !important;
}
#tools-menu li.selected button:first-child path {
#tools-menu li.selected button:first-child path, #tools-menu li.selected button:first-child ellipse {
fill: $baseselectedicon;
}

View File

@ -1,4 +1,4 @@
const featureToggles = (function featureTogglesModule() {
/*const featureToggles = (function featureTogglesModule() {
const ellipseToolLocalStorageKey = 'feature_ellipseTool';
@ -30,4 +30,4 @@ const featureToggles = (function featureTogglesModule() {
}
})();
*/

View File

@ -6,6 +6,7 @@ const ToolManager = (() => {
tools["eraser"] = new EraserTool("eraser", {type: 'html'}, switchTool);
tools["rectangle"] = new RectangleTool("rectangle", {type: 'html'}, switchTool);
tools["line"] = new LineTool("line", {type: 'html'}, switchTool);
tools["ellipse"] = new EllipseTool("ellipse", {type: 'html'}, switchTool);
tools["fill"] = new FillTool("fill", {type: 'cursor', style: 'crosshair'}, switchTool);
tools["eyedropper"] = new EyeDropperTool("eyedropper", {type: 'cursor', style: 'crosshair'}, switchTool);

View File

@ -37,6 +37,7 @@
//=include tools/EraserTool.js
//=include tools/LineTool.js
//=include tools/RectangleTool.js
//=include tools/EllipseTool.js
//=include tools/FillTool.js
//=include tools/EyeDropperTool.js
//=include tools/PanTool.js
@ -69,7 +70,7 @@ PresetModule.instrumentPresetMenu();
//when the page is done loading, you can get ready to start
window.onload = function () {
featureToggles.onLoad();
//featureToggles.onLoad();
ToolManager.currentTool().updateCursor();

143
js/tools/EllipseTool.js Normal file
View File

@ -0,0 +1,143 @@
class EllipseTool extends DrawingTool {
// Saving the empty rect svg
emptyEllipseSVG = document.getElementById("ellipse-empty-button-svg");
// and the full rect svg so that I can change them when the user changes rect modes
fullEllipseSVG = document.getElementById("ellipse-full-button-svg");
// Current fill mode
currFillMode = 'empty';
switchFunction = null;
constructor(name, options, switchFunction) {
super(name, options);
this.switchFunction = switchFunction;
Events.on('click', this.mainButton, this.changeFillType.bind(this));
Events.on('click', this.biggerButton, this.increaseSize.bind(this));
Events.on('click', this.smallerButton, this.decreaseSize.bind(this));
}
changeFillType() {
if (this.isSelected)
if (this.currFillMode == 'empty') {
this.currFillMode = 'fill';
this.emptyEllipseSVG.setAttribute('display', 'none');
this.fullEllipseSVG.setAttribute('display', 'visible');
}
else {
this.currFillMode = 'empty'
this.emptyEllipseSVG.setAttribute('display', 'visible');
this.fullEllipseSVG.setAttribute('display', 'none');
}
else
this.switchFunction(this);
}
onStart(mousePos) {
super.onStart(mousePos);
// Putting the tmp layer on top of everything
currFile.TMPLayer.canvas.style.zIndex = parseInt(currFile.currentLayer.canvas.style.zIndex, 10) + 1;
this.startMousePos[0] = Math.floor(mousePos[0] / currFile.zoom) + 0.5;
this.startMousePos[1] = Math.floor(mousePos[1] / currFile.zoom) + 0.5;
new HistoryState().EditCanvas();
}
onDrag(mousePos, cursorTarget) {
// Drawing the rect at the right position
this.drawRect(Math.floor(mousePos[0] / currFile.zoom) + 0.5, Math.floor(mousePos[1] / currFile.zoom) + 0.5);
}
/** Finishes drawing the rect, decides the end coordinates and moves the preview rectangle to the
* current layer
*
* @param {*} mousePos The position of the mouse when the user stopped dragging
*/
onEnd(mousePos) {
super.onEnd(mousePos);
let tmpContext = currFile.TMPLayer.context;
let endRectX = Math.floor(mousePos[0] / currFile.zoom) + 0.5;
let endRectY = Math.floor(mousePos[1] / currFile.zoom) + 0.5;
let startRectX = this.startMousePos[0];
let startRectY = this.startMousePos[1];
// Inverting end and start (start must always be the top left corner)
if (endRectX < startRectX) {
let tmp = endRectX;
endRectX = startRectX;
startRectX = tmp;
}
// Same for the y
if (endRectY < startRectY) {
let tmp = endRectY;
endRectY = startRectY;
startRectY = tmp;
}
// Drawing the rect
startRectY -= 0.5;
endRectY -= 0.5;
endRectX -= 0.5;
startRectX -= 0.5;
// Setting the correct linewidth and colour
currFile.currentLayer.context.lineWidth = this.currSize;
// Drawing the rect using 4 lines
currFile.currentLayer.drawLine(startRectX, startRectY, endRectX, startRectY, this.currSize);
currFile.currentLayer.drawLine(endRectX, startRectY, endRectX, endRectY, this.currSize);
currFile.currentLayer.drawLine(endRectX, endRectY, startRectX, endRectY, this.currSize);
currFile.currentLayer.drawLine(startRectX, endRectY, startRectX, startRectY, this.currSize);
// If I have to fill it, I do so
if (this.currFillMode == 'fill') {
currFile.currentLayer.context.fillRect(startRectX, startRectY, endRectX - startRectX, endRectY - startRectY);
}
// Update the layer preview
currFile.currentLayer.updateLayerPreview();
// Clearing the tmp canvas
tmpContext.clearRect(0, 0, currFile.TMPLayer.canvas.width, currFile.TMPLayer.canvas.height);
}
onSelect() {
super.onSelect();
}
onDeselect() {
super.onDeselect();
}
/** Draws a rectangle with end coordinates given by x and y on the tmp layer (draws
* the preview for the rectangle tool)
*
* @param {*} x The current end x of the rectangle
* @param {*} y The current end y of the rectangle
*/
drawRect(x, y) {
// Getting the tmp context
let tmpContext = currFile.TMPLayer.context;
// Clearing the tmp canvas
tmpContext.clearRect(0, 0, currFile.TMPLayer.canvas.width, currFile.TMPLayer.canvas.height);
// Drawing the rect
tmpContext.lineWidth = this.currSize;
// Drawing the rect
tmpContext.beginPath();
if ((this.currSize % 2 ) == 0) {
tmpContext.rect(this.startMousePos[0] - 0.5, this.startMousePos[1] - 0.5, x - this.startMousePos[0], y - this.startMousePos[1]);
}
else {
tmpContext.rect(this.startMousePos[0], this.startMousePos[1], x - this.startMousePos[0], y - this.startMousePos[1]);
}
tmpContext.setLineDash([]);
tmpContext.stroke();
}
}

View File

@ -1,144 +0,0 @@
// Saving the empty rect svg
var emptyEllipseSVG = document.getElementById("ellipse-empty-button-svg");
// and the full rect svg so that I can change them when the user changes rect modes
var fullEllipseSVG = document.getElementById("ellipse-full-button-svg");
// The start mode is empty ellipse
var ellipseDrawMode = 'empty';
// I'm not drawing a ellipse at the beginning
var isDrawingEllipse = false;
// Ellipse coordinates
let startEllipseX;
let startEllipseY;
let endEllipseX;
let endEllipseY;
// TODO: [ELLIPSE] Make it draw ellipse instead of copy-pasted rectangle
/** Starts drawing the ellipse, saves the start coordinates
*
* @param {*} mouseEvent
*/
function startEllipseDrawing(mouseEvent) {
// Putting the vfx layer on top of everything
VFXLayer.canvas.style.zIndex = parseInt(currentLayer.canvas.style.zIndex, 10) + 1;;
// Updating flag
isDrawingEllipse = true;
// Saving the start coords of the ellipse
let cursorPos = Input.getCursorPosition(mouseEvent);
startEllipseX = Math.floor(cursorPos[0] / zoom) + 0.5;
startEllipseY = Math.floor(cursorPos[1] / zoom) + 0.5;
drawEllipse(startEllipseX, startEllipseY);
}
// TODO: [ELLIPSE] Make it draw ellipse instead of copy-pasted rectangle
/** Updates the ellipse preview depending on the position of the mouse
*
* @param {*} mouseEvent The mouseEvent from which we'll get the mouse position
*/
function updateEllipseDrawing(mouseEvent) {
let pos = Input.getCursorPosition(mouseEvent);
// Drawing the ellipse at the right position
drawEllipse(Math.round(pos[0] / zoom) + 0.5, Math.round(pos[1] / zoom) + 0.5);
}
// TODO: [ELLIPSE] Make it draw ellipse instead of copy-pasted rectangle
/** Finishes drawing the ellipse, decides the end coordinates and moves the preview ellipse to the
* current layer
*
* @param {*} mouseEvent event from which we'll get the mouse position
*/
function endEllipseDrawing(mouseEvent) {
// Getting the end position
let currentPos = Input.getCursorPosition(mouseEvent);
let vfxContext = VFXLayer.context;
endEllipseX = Math.round(currentPos[0] / zoom) + 0.5;
endEllipseY = Math.round(currentPos[1] / zoom) + 0.5;
// Inverting end and start (start must always be the top left corner)
if (endEllipseX < startEllipseX) {
let tmp = endEllipseX;
endEllipseX = startEllipseX;
startEllipseX = tmp;
}
// Same for the y
if (endEllipseY < startEllipseY) {
let tmp = endEllipseY;
endEllipseY = startEllipseY;
startEllipseY = tmp;
}
// Resetting this
isDrawingEllipse = false;
// Drawing the ellipse
startEllipseY -= 0.5;
endEllipseY -= 0.5;
endEllipseX -= 0.5;
startEllipseX -= 0.5;
// Setting the correct linewidth
currentLayer.context.lineWidth = tool.ellipse.brushSize;
// Drawing the ellipse using 4 lines
currentLayer.drawLine(startEllipseX, startEllipseY, endEllipseX, startEllipseY, tool.ellipse.brushSize);
currentLayer.drawLine(endEllipseX, startEllipseY, endEllipseX, endEllipseY, tool.ellipse.brushSize);
currentLayer.drawLine(endEllipseX, endEllipseY, startEllipseX, endEllipseY, tool.ellipse.brushSize);
currentLayer.drawLine(startEllipseX, endEllipseY, startEllipseX, startEllipseY, tool.ellipse.brushSize);
// If I have to fill it, I do so
if (ellipseDrawMode == 'fill') {
currentLayer.context.fillRect(startEllipseX, startEllipseY, endEllipseX - startEllipseX, endEllipseY - startEllipseY);
}
// Clearing the vfx canvas
vfxContext.clearRect(0, 0, VFXLayer.canvas.width, VFXLayer.canvas.height);
}
// TODO: [ELLIPSE] Make it draw ellipse instead of copy-pasted rectangle
/** Draws a ellipse with end coordinates given by x and y on the VFX layer (draws
* the preview for the ellipse tool)
*
* @param {*} x The current end x of the ellipse
* @param {*} y The current end y of the ellipse
*/
function drawEllipse(x, y) {
// Getting the vfx context
let vfxContext = VFXLayer.context;
// Clearing the vfx canvas
vfxContext.clearRect(0, 0, VFXLayer.canvas.width, VFXLayer.canvas.height);
// Drawing the ellipse
vfxContext.lineWidth = tool.ellipse.brushSize;
// Drawing the ellipse
vfxContext.beginPath();
if ((tool.ellipse.brushSize % 2 ) == 0) {
vfxContext.rect(startEllipseX - 0.5, startEllipseY - 0.5, x - startEllipseX, y - startEllipseY);
}
else {
vfxContext.rect(startEllipseX, startEllipseY, x - startEllipseX, y - startEllipseY);
}
vfxContext.setLineDash([]);
vfxContext.stroke();
}
/** Sets the correct tool icon depending on its mode
*
*/
function setEllipseToolSvg() {
console.log("set eilipse svg");
if (ellipseDrawMode == 'empty') {
emptyEllipseSVG.setAttribute('display', 'visible');
fullEllipseSVG.setAttribute('display', 'none');
}
else {
emptyEllipseSVG.setAttribute('display', 'none');
fullEllipseSVG.setAttribute('display', 'visible');
}
}

View File

@ -1,6 +1,9 @@
<svg width="512" height="512" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
<g>
<ellipse stroke="#000" stroke-width="32" fill="none" cx="255.50001" cy="255.5" id="svg_20" rx="239" ry="187.5"/>
</g>
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 18 18" style="enable-background:new 0 0 17 17;" xml:space="preserve">
<g>
<ellipse cx="9" cy="9" rx="7.5" ry="6.2" stroke="black" stroke-width="2" fill="none" fill-opacity="0"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 221 B

After

Width:  |  Height:  |  Size: 471 B

View File

@ -1,22 +1,8 @@
<svg width="512" height="512" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
<g>
<title>Layer 1</title>
<g id="svg_4"/>
<g id="svg_5"/>
<g id="svg_6"/>
<g id="svg_7"/>
<g id="svg_8"/>
<g id="svg_9"/>
<g id="svg_10"/>
<g id="svg_11"/>
<g id="svg_12"/>
<g id="svg_13"/>
<g id="svg_14"/>
<g id="svg_15"/>
<g id="svg_16"/>
<g id="svg_17"/>
<g id="svg_18"/>
<ellipse stroke="#000" stroke-width="32" fill="#000000" cx="255.50001" cy="255.5" id="svg_20" rx="239" ry="187.5"/>
</g>
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 18 18" style="enable-background:new 0 0 17 17;" xml:space="preserve">
<g>
<ellipse stroke="none" cx="9" cy="9" rx="8.5" ry="7.2"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 528 B

After

Width:  |  Height:  |  Size: 422 B

View File

@ -24,10 +24,7 @@
</ul>
</li>
<!-- TODO: [ELLIPSE] Once ellipse is ready for release make it visible by default -->
<li class="expanded" id="tools-menu--ellipse" style="display: none">
<!-- TODO: [ELLIPSE] Decide on a shortcut to use. "S" was chosen without any in-team consultation. -->
<!-- TODO: [ELLIPSE] Decide on icons to use. Current ones are quickly prepared drafts and display with incorrect color. -->
<li class="expanded">
<button title="Ellipse Tool (S)" id="ellipse-button">
{{svg "ellipse.svg" width="24" height="24" id = "ellipse-empty-button-svg"}}
{{svg "filledellipse.svg" width="24" height="24" id = "ellipse-full-button-svg" display = "none"}}