Created
November 16, 2021 10:17
-
-
Save muhsinokcu/718098637897d086769ffbb2a4121554 to your computer and use it in GitHub Desktop.
Paint w/ canvas
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
h1 Paint | |
p.legend Draw me like one of your french girl in the box below | |
canvas#paint(width=270)(height=150) | |
button#clear clear | |
h2 Painted base64 | |
textarea#data-paint.data |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* This method returns the relative offset x/y for a mouse cursor position in an element such as canvas | |
* @param {object} e - the event object</param> | |
* @param {string} id - the id of the element in which the mouse is positioned | |
*/ | |
function getMouseOffset (_e, _el) { | |
let xpos, ypos; | |
if (typeof _e.offsetX === 'undefined') { // ff hack | |
// dans ce cas, jQuery facilite l'appel d'offset | |
xpos = _e.pageX - $(_el).offset().left; | |
ypos = _e.pageY - $(_el).offset().top; | |
} else { | |
xpos = _e.offsetX; | |
ypos = _e.offsetY; | |
} | |
const pointerPos = { x: xpos, y: ypos }; | |
console.log(pointerPos); | |
return pointerPos; | |
} | |
/** | |
* Extends Canvas element to use it as a paint element | |
*/ | |
var extendCanvas = function (canvas) { | |
if (typeof canvas === 'string') { | |
canvas = document.getElementById(canvas); | |
} | |
try { | |
canvas.ctx = canvas.getContext('2d'); | |
canvas.ctx.strokeStyle = "black"; | |
canvas.ctx.lineWidth = 2; | |
canvas.lineJoin = "round"; | |
canvas.ctx.scale(1, 1); | |
canvas.isLocked = false; | |
canvas.hasDrawn = false; | |
canvas.disableSave = true; | |
canvas.pixels = []; | |
canvas.cpixels = []; | |
canvas.xyLast = {}; | |
canvas.xyAddLast = {}; | |
canvas.calculate = false; | |
//start drawing a stroke from a position | |
canvas.draw = function (x, y) { | |
this.ctx.lineTo(x, y); | |
this.ctx.stroke(); | |
}; | |
//Get the mouse position in the canvas | |
canvas.getCursorCoords = function (e) { | |
return getMouseOffset(e, this); | |
}; | |
//Clear the content of the canvas element | |
canvas.clear = function () { | |
if (!this.isLocked) { | |
this.ctx.clearRect(0, 0, this.width, this.height); | |
this.emptyRelatedField(); | |
this.isModified(false); | |
} | |
}; | |
//Lock the canvas element | |
canvas.lock = function (shouldLock) { | |
this.isLocked = shouldLock; | |
if (shouldLock) { | |
$(this).addClass('disabled'); | |
} else { | |
$(this).removeClass('disabled'); | |
} | |
}; | |
canvas.isModified = function (wasModified) { | |
if (wasModified) { | |
this.fillRelatedField(); | |
$(this).addClass('modified'); | |
} else { | |
this.emptyRelatedField(); | |
$(this).removeClass('modified'); | |
} | |
}; | |
//Empty the field that contains the base64 string | |
canvas.emptyRelatedField = function () { | |
var relatedField = document.getElementById('data-' + this.id); | |
if (relatedField) { | |
relatedField.value = ""; | |
} | |
}; | |
//Fill the filed that contains the base64 string | |
canvas.fillRelatedField = function () { | |
document.getElementById('data-' + this.id).value = this.toDataURL(); | |
}; | |
//Load a passed image | |
canvas.loadImage = function (base64Img) { | |
//if (!canvas.isLocked) { | |
var image = new Image(); | |
var thisCanvas = this; | |
if (base64Img.indexOf("data:image/png;base64,") === -1) { | |
base64Img = "data:image/png;base64," + base64Img; | |
} | |
image.src = base64Img; | |
image.onload = function () { | |
var offset = { x: 0, y: 0 }; | |
//center the image in the canvas | |
try { | |
offset.x = ((thisCanvas.width / 2) - (image.width / 2)); | |
offset.y = ((thisCanvas.height / 2) - (image.height / 2)); | |
if (offset.x < 0 || offset.y < 0) { | |
throw { | |
name: "Painting error", | |
message: "Image has a negativ offset.", | |
toString: function () { return this.name + ": " + this.message; } | |
}; | |
} | |
} catch (err) { | |
offset = { x: 0, y: 0 }; | |
} | |
thisCanvas.ctx.drawImage(image, offset.x, offset.y); | |
}; | |
}; | |
/** | |
* This method remove the event by default, to load them only when clicking in the canvas | |
*/ | |
function remove_event_listeners() { | |
canvas.removeEventListener('mouseup', on_mouseup, false); | |
canvas.removeEventListener('touchend', on_mouseup, false); | |
canvas.removeEventListener('pointerup', on_mouseup, false); | |
canvas.removeEventListener('mousemove', on_mousemove, false); | |
canvas.removeEventListener('pointermove', on_mousemove, false); | |
document.body.removeEventListener('mouseup', on_mouseup, false); | |
document.body.removeEventListener('touchend', on_mouseup, false); | |
document.body.removeEventListener('pointerup', on_mouseup, false); | |
}; | |
//Event when the mouse is clicked | |
function on_mousedown(e) { | |
console.log('mousedown'); | |
if (!canvas.isLocked) { | |
e.preventDefault(); | |
e.stopPropagation(); | |
canvas.hasDrawn = false; | |
//we activate the mouse and touch events | |
canvas.addEventListener('mouseup', on_mouseup, false); | |
canvas.addEventListener('touchend', on_mouseup, false); | |
canvas.addEventListener('pointerup', on_mouseup, false); | |
canvas.addEventListener('mousemove', on_mousemove, false); | |
canvas.addEventListener('pointermove', on_mousemove, false); | |
document.body.addEventListener('mouseup', on_mouseup, false); | |
document.body.addEventListener('touchend', on_mouseup, false); | |
document.body.addEventListener('pointerup', on_mouseup, false); | |
var xy = canvas.getCursorCoords(e); | |
canvas.ctx.beginPath(); | |
canvas.pixels.push('moveStart'); | |
canvas.ctx.moveTo(xy.x, xy.y); | |
canvas.pixels.push(xy.x, xy.y); | |
canvas.xyLast = xy; | |
} | |
}; | |
//Event when the mouse is moving. | |
function on_mousemove(e, finish) { | |
if (!canvas.isLocked) { | |
e.preventDefault(); | |
e.stopPropagation(); | |
canvas.hasDrawn = true; | |
var xy = canvas.getCursorCoords(e); | |
var xyAdd = { | |
x: (canvas.xyLast.x + xy.x) / 2, | |
y: (canvas.xyLast.y + xy.y) / 2 | |
}; | |
if (canvas.calculate) { | |
var xLast = (canvas.xyAddLast.x + canvas.xyLast.x + xyAdd.x) / 3; | |
var yLast = (canvas.xyAddLast.y + canvas.xyLast.y + xyAdd.y) / 3; | |
canvas.pixels.push(xLast, yLast); | |
} else { | |
canvas.calculate = true; | |
} | |
canvas.ctx.quadraticCurveTo(canvas.xyLast.x, canvas.xyLast.y, xyAdd.x, xyAdd.y); | |
canvas.pixels.push(xyAdd.x, xyAdd.y); | |
canvas.ctx.stroke(); | |
canvas.ctx.beginPath(); | |
canvas.ctx.moveTo(xyAdd.x, xyAdd.y); | |
canvas.xyAddLast = xyAdd; | |
canvas.xyLast = xy; | |
} | |
}; | |
//Event when the click is released | |
function on_mouseup(e) { | |
console.log('mouseup'); | |
if (!canvas.isLocked) { | |
if (!canvas.hasDrawn) {//If there was no move, draw a single point | |
var pos = canvas.getCursorCoords(e); | |
canvas.ctx.rect(pos.x, pos.y, 1, 1); | |
} | |
remove_event_listeners(); | |
canvas.disableSave = false; | |
canvas.ctx.stroke(); | |
canvas.pixels.push('e'); | |
canvas.calculate = false; | |
canvas.isModified(true); | |
canvas.hasDrawn = false; | |
} | |
}; | |
//We activate only the click or touch event. | |
// ReSharper disable once Html.EventNotResolved correspond à un événement de toucher sur écran tactile | |
canvas.addEventListener('mousedown', on_mousedown, false); | |
canvas.addEventListener('touchstart', on_mousedown, false); | |
canvas.addEventListener('pointerdown', on_mousedown, false); | |
} catch (err) { | |
//If someting went wrong, notify the user. | |
console.error("Canvas not initialized. Painting is not activated."); | |
} | |
return canvas; | |
}; | |
var myC = extendCanvas('paint'); | |
$('#clear').on('click', (e) => { | |
myC.clear(); | |
myC.emptyRelatedField(); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body { | |
font-family: Arial; | |
} | |
#paint { | |
border: 1px solid #333; | |
display: block; | |
margin: 20px 0; | |
} | |
#clear { | |
margin: 8px 0; | |
padding: 4px 8px; | |
font-size: 1rem; | |
} | |
.data { | |
width: 266px; | |
height: 150px; | |
margin: 5px 0; | |
} | |
.legend { | |
font-style: italic; | |
color: grey; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment