Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html lang="fr">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Paint personnalisé</title>
- <style>
- #drawingCanvas {
- border: 1px solid black;
- touch-action: none;
- position: relative;
- z-index: 1;
- background-color: rgba(0,0,0,0); /* Transparency added */
- }
- .controls {
- margin-bottom: 10px;
- position: sticky;
- top: 0;
- background: #ffffff;
- z-index: 10;
- padding: 5px;
- }
- #textVisual {
- position: absolute;
- z-index: 2;
- display: none;
- cursor: pointer;
- background-color: rgba(255,255,255,0.7);
- border: 1px dashed black;
- padding: 3px;
- }
- </style>
- </head>
- <body>
- <h1 id="paint">Paint</h1>
- <div class="controls">
- Forme: <select id="shapeSelector">
- <option value="brush">Pinceau</option>
- <option value="line">Ligne</option>
- <option value="rectangle">Rectangle</option>
- <option value="circle">Cercle</option>
- <option value="triangle">Triangle</option>
- <option value="text">Texte</option>
- <option value="eraser">Gomme</option>
- <option value="eyedropper">Compte-goutte</option>
- <option value="fill">Remplissage</option>
- </select>
- <input type="checkbox" id="square"> Square
- Taille: <input type="range" id="size" min="1" max="50" value="5">
- Couleur: <input type="color" id="colorPicker" value="#000000">
- Texte: <input type="text" id="drawText">
- Style de texte: <select id="textStyle">
- <option value="normal">Normal</option>
- <option value="italic">Italique</option>
- <option value="bold">Gras</option>
- </select>
- Police de texte: <select id="fontSelector">
- <option value="Arial">Arial</option>
- <option value="Verdana">Verdana</option>
- <option value="Times New Roman">Times New Roman</option>
- <option value="Pristina">Pristina</option>
- </select>
- Position X: <input type="range" id="textPositionX" min="0" max="100" value="50">
- Position Y: <input type="range" id="textPositionY" min="0" max="100" value="50">
- <div id="textPreview"></div>
- <button onclick="placeText()">Placer le texte</button>
- <input type="checkbox" id="lastPoint"> À partir du dernier point
- <button onclick="saveCanvas()">Enregistrer</button>
- <button onclick="document.getElementById('fileLoader').click();">Charger</button>
- <input type="file" id="fileLoader" style="display: none;" onchange="loadImage(event)">
- <button onclick="resetCanvas()">Réinitialiser</button>
- <button onclick="undo()">Effacer le dernier objet</button>
- //<input type="range" id="zoomSlider" min="10" max="200" value="100" onchange="adjustZoom()"> % Zoom
- <!-- Zoom horizontal -->
- <label for="zoomHorizontal">Zoom Horizontal:</label>
- <input type="range" id="zoomHorizontal" min="10" max="200" value="100" onchange="adjustZoomHorizontal()">
- <span id="zoomHorizontalValue">100%</span>
- <!-- Zoom vertical -->
- <label for="zoomVertical">Zoom Vertical:</label>
- <input type="range" id="zoomVertical" min="10" max="200" value="100" onchange="adjustZoomVertical()">
- <span id="zoomVerticalValue">100%</span>
- </div>
- <canvas id="drawingCanvas" width="800" height="600"></canvas>
- <div id="textVisual"></div>
- <script>
- let canvas = document.getElementById('drawingCanvas');
- let ctx = canvas.getContext('2d');
- let isDrawing = false;
- let startPoint = {};
- let lastPoint = null;
- let square = null;
- let shape = "brush";
- let currentSize = 5;
- let tempCanvas = document.createElement('canvas');
- tempCanvas.width = canvas.width;
- tempCanvas.height = canvas.height;
- let tempCtx = tempCanvas.getContext('2d');
- let history = [];
- let historyIndex = -1;
- function getAdjustedMousePos(e) {
- const rect = canvas.getBoundingClientRect();
- return {
- x: (e.clientX - rect.left) * (canvas.width / rect.width),
- y: (e.clientY - rect.top) * (canvas.height / rect.height)
- };
- }
- function saveToHistory() {
- historyIndex++;
- history[historyIndex] = tempCtx.getImageData(0, 0, canvas.width, canvas.height);
- if (historyIndex < history.length - 1) {
- history.length = historyIndex + 1;
- }
- }
- canvas.addEventListener('mousedown', (e) => {
- saveToHistory();
- isDrawing = true;
- if (document.getElementById('lastPoint').checked && lastPoint) {
- startPoint = lastPoint;
- } else {
- startPoint = getAdjustedMousePos(e);
- }
- });
- canvas.addEventListener('mousemove', draw);
- canvas.addEventListener('mouseup', (e) => {
- isDrawing = false;
- draw(e);
- lastPoint = getAdjustedMousePos(e);
- finalizeDrawing();
- });
- document.getElementById('shapeSelector').addEventListener('change', (e) => {
- shape = e.target.value;
- });
- document.getElementById('size').addEventListener('change', (e) => {
- currentSize = e.target.value;
- });
- /*function adjustZoom() {
- let zoomValue = document.getElementById('zoomSlider').value;
- canvas.style.transform = `scale(${zoomValue / 100})`;
- canvas.style.transformOrigin = 'top left';
- }*/
- function adjustZoomHorizontal() {
- let zoomValue = document.getElementById('zoomHorizontal').value;
- canvas.style.transform = `scaleX(${zoomValue / 100})`;
- document.getElementById('zoomHorizontalValue').innerText = `${zoomValue}%`;
- }
- function adjustZoomVertical() {
- let zoomValue = document.getElementById('zoomVertical').value;
- canvas.style.transform = `scaleY(${zoomValue / 100})`;
- document.getElementById('zoomVerticalValue').innerText = `${zoomValue}%`;
- }
- // Créez un autre canvas pour contenir le texte
- let textCanvas = document.createElement('canvas');
- textCanvas.width = canvas.width;
- textCanvas.height = canvas.height;
- let textCtx = textCanvas.getContext('2d');
- function placeText() {
- let fontValue = document.getElementById('fontSelector').value;
- let fontStyle = document.getElementById('textStyle').value;
- let textContent = document.getElementById('drawText').value;
- let posX = document.getElementById('textPositionX').value / 100 * canvas.width;
- let posY = document.getElementById('textPositionY').value / 100 * canvas.height;
- // Effacez la zone où se trouve le texte en dessinant un rectangle transparent
- //ctx.clearRect(posX, posY - currentSize * 3, textCanvas.width, currentSize * 3);
- // Dessinez le texte sur le canvas principal
- if (textContent.trim() !== '') {
- ctx.font = `${fontStyle} ${currentSize * 3}px ${fontValue}`;
- ctx.fillStyle = document.getElementById('colorPicker').value;
- ctx.fillText(textContent, posX, posY);
- }
- finalizeDrawing(); // Redessine tempCanvas et conserve l'historique
- // Effacez la prévisualisation du texte
- document.getElementById('textPreview').textContent = '';
- }
- let textVisual = document.getElementById('textVisual');
- textVisual.addEventListener('mousedown', startTextDrag);
- textVisual.addEventListener('mousemove', doTextDrag);
- textVisual.addEventListener('mouseup', stopTextDrag);
- textVisual.addEventListener('touchstart', startTextDrag);
- textVisual.addEventListener('touchmove', doTextDrag);
- textVisual.addEventListener('touchend', stopTextDrag);
- function startTextDrag(e) {
- if (shape === 'text') {
- e.preventDefault();
- isDrawing = true;
- textVisual.style.display = 'block';
- let textContent = document.getElementById('drawText').value;
- textVisual.innerText = textContent;
- let posX, posY;
- if (e.type === 'touchstart') {
- posX = e.touches[0].clientX;
- posY = e.touches[0].clientY;
- } else {
- posX = e.clientX;
- posY = e.clientY;
- }
- textVisual.style.left = `${posX}px`;
- textVisual.style.top = `${posY}px`;
- }
- }
- function doTextDrag(e) {
- if (isDrawing && shape === 'text') {
- e.preventDefault();
- let posX, posY;
- if (e.type === 'touchmove') {
- posX = e.touches[0].clientX;
- posY = e.touches[0].clientY;
- } else {
- posX = e.clientX;
- posY = e.clientY;
- }
- textVisual.style.left = `${posX}px`;
- textVisual.style.top = `${posY}px`;
- }
- }
- function stopTextDrag(e) {
- if (isDrawing && shape === 'text') {
- isDrawing = false;
- let posX, posY;
- if (e.type === 'touchend') {
- let touch = e.changedTouches[0];
- posX = touch.clientX;
- posY = touch.clientY;
- } else {
- posX = e.clientX;
- posY = e.clientY;
- }
- const canvasRect = canvas.getBoundingClientRect();
- const canvasX = posX - canvasRect.left;
- const canvasY = posY - canvasRect.top;
- // Mise à jour des valeurs textPositionX et textPositionY en pourcentage
- document.getElementById('textPositionX').value = (canvasX / canvasRect.width) * 100;
- document.getElementById('textPositionY').value = (canvasY / canvasRect.height) * 100;
- placeText();
- textVisual.style.display = 'none';
- }
- }
- document.getElementById('shapeSelector').addEventListener('change', (e) => {
- shape = e.target.value;
- switch (shape) {
- case "brush":
- case "line":
- case "circle":
- case "rectangle":
- case "triangle":
- case "fill":
- canvas.style.cursor = progress;
- //"url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgdmlld0JveD0iMCAwIDIwIDIwIj4KPHBhdGggZD0iTTEwLDEuNWMtNC42LDAuMS04LjMsMy44LTksOC42QzEsMTEsMiwxMiwyLDEyLjNjMC41LDAuOSwyLjIsMi43LDQsMy45YzEuOCwxLjEsMy43LDEuOSw1LjUsMS45YzIuMiwwLDQuMi0xLDEtNEw3LDEwTDExLDVsMi4zLDNjMi43LTIuNiwyLjMtNi43LDEuMi05LjJDMTQuMiwyLjIsMTIsMS42LDEwLDEuNXoiIGZpbGw9IiMwMDAwMDAiLz4KPC9zdmc+Cg==') 10 10, auto";
- break;
- case "text":
- canvas.style.cursor = "text";
- break;
- case "eraser":
- canvas.style.cursor = "pointer";
- break;
- case "eyedropper":
- canvas.style.cursor = crosshair;
- //"url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgdmlld0JveD0iMCAwIDIwIDIwIj4KPHBhdGggZD0iTTE2LjIsNC4ybC0xLjQtMS40Yy0wLjQtMC40LTEtMC40LTEuNCwwTDEuMiwxNC4yYy0wLjQsMC40LTAuNCwxLDAsMS40bDEuNCwxLjRjMC40LDAuNCwxLDAuNCwxLjQsMEwxNi4yLDUuNkMxNi42LDUuMiwxNi42LDQuNiwxNi4yLDQuMnoiIGZpbGw9IiMwMDAwMDAiLz4KPC9zdmc+Cg==') 10 10, auto";
- break;
- }
- });
- function lerp(point1, point2, t) {
- return {
- x: point1.x + t * (point2.x - point1.x),
- y: point1.y + t * (point2.y - point1.y)
- };
- }
- function draw(e) {
- if (!isDrawing) return;
- const currentPoint = getAdjustedMousePos(e);
- ctx.strokeStyle = document.getElementById('colorPicker').value;
- ctx.lineWidth = currentSize;
- let currentCtx = ctx; // par défaut, on dessine sur le canvas principal
- switch (shape) {
- case "brush":
- if (document.getElementById('square').checked) {
- if (document.getElementById('lastPoint').checked && lastPoint) {
- ctx.lineTo(currentPoint.x, currentPoint.y);
- ctx.stroke();
- ctx.beginPath();
- const halfLineWidth = ctx.lineWidth / 2;
- ctx.fillStyle = document.getElementById('colorPicker').value; // Définir la couleur de remplissage
- ctx.fillRect(currentPoint.x - halfLineWidth, currentPoint.y - halfLineWidth, ctx.lineWidth, ctx.lineWidth);
- ctx.fill();
- ctx.moveTo(currentPoint.x, currentPoint.y);
- } else {
- const distance = Math.sqrt((currentPoint.x - startPoint.x)**2 + (currentPoint.y - startPoint.y)**2);
- const step = ctx.lineWidth;
- const steps = Math.ceil(distance / step);
- const dx = (currentPoint.x - startPoint.x) / steps;
- const dy = (currentPoint.y - startPoint.y) / steps;
- for (let i = 0; i < steps; i++) {
- const x = startPoint.x + dx * i;
- const y = startPoint.y + dy * i;
- ctx.beginPath();
- const halfStep = step / 2;
- ctx.fillStyle = document.getElementById('colorPicker').value; // Définir la couleur de remplissage
- ctx.fillRect(x - halfStep, y - halfStep, step, step);
- ctx.fill();
- }
- }
- startPoint = currentPoint;
- ctx.stroke();
- break;
- } else {
- if (document.getElementById('lastPoint').checked && lastPoint) {
- ctx.lineTo(currentPoint.x, currentPoint.y);
- ctx.beginPath();
- ctx.arc(currentPoint.x, currentPoint.y, ctx.lineWidth / 2, 0, Math.PI * 2, false);
- ctx.fill();
- ctx.moveTo(currentPoint.x, currentPoint.y);
- ctx.stroke();
- } else {
- const distance = Math.sqrt((currentPoint.x - startPoint.x)**2 + (currentPoint.y - startPoint.y)**2);
- const radius = ctx.lineWidth / 2;
- const step = ctx.lineWidth;
- const steps = Math.ceil(distance / step);
- const dx = (currentPoint.x - startPoint.x) / steps;
- const dy = (currentPoint.y - startPoint.y) / steps;
- for (let i = 0; i < steps; i++) {
- const x = startPoint.x + dx * i;
- const y = startPoint.y + dy * i;
- ctx.beginPath();
- ctx.arc(x, y, radius, 0, Math.PI * 2, false);
- ctx.fill();
- ctx.stroke();
- }
- }
- startPoint = currentPoint;
- break;
- }
- case "eraser":
- ctx.clearRect(currentPoint.x - currentSize / 2, currentPoint.y - currentSize / 2, currentSize, currentSize);
- break;
- case "line":
- case "rectangle":
- case "circle":
- case "triangle":
- switch (shape) {
- case "line":
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- ctx.drawImage(tempCanvas, 0, 0);
- ctx.beginPath();
- ctx.moveTo(startPoint.x, startPoint.y);
- ctx.lineTo(currentPoint.x, currentPoint.y);
- ctx.stroke();
- break;
- case "rectangle":
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- ctx.drawImage(tempCanvas, 0, 0);
- let rectWidth = currentPoint.x - startPoint.x;
- let rectHeight = currentPoint.y - startPoint.y;
- ctx.strokeRect(startPoint.x, startPoint.y, rectWidth, rectHeight);
- break;
- case "circle":
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- ctx.drawImage(tempCanvas, 0, 0);
- ctx.beginPath();
- let radius = Math.sqrt(Math.pow(currentPoint.x - startPoint.x, 2) + Math.pow(currentPoint.y - startPoint.y, 2));
- ctx.arc(startPoint.x, startPoint.y, radius, 0, Math.PI * 2);
- ctx.stroke();
- break;
- case "triangle":
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- ctx.drawImage(tempCanvas, 0, 0);
- ctx.beginPath();
- ctx.moveTo(startPoint.x, startPoint.y);
- ctx.lineTo(startPoint.x + (currentPoint.x - startPoint.x), currentPoint.y);
- ctx.lineTo(startPoint.x - (currentPoint.x - startPoint.x), currentPoint.y);
- ctx.closePath();
- ctx.stroke();
- break;
- }
- break;
- }
- }
- canvas.addEventListener('click', (e) => {
- const rect = canvas.getBoundingClientRect();
- const x = Math.round(e.clientX - rect.left);
- const y = Math.round(e.clientY - rect.top);
- switch (shape) {
- case "fill":
- const fillColor = hexToRgb(document.getElementById('colorPicker').value);
- const targetColor = ctx.getImageData(x, y, 1, 1).data.slice(0, 3); // Prendre seulement r, g, b
- floodFill(x, y, fillColor);
- console.log("Outil de remplissage activé");
- break;
- }
- });
- canvas.addEventListener('click', (e) => {
- const rect = canvas.getBoundingClientRect();
- const x = Math.round(e.clientX - rect.left);
- const y = Math.round(e.clientY - rect.top);
- switch (shape) {
- case "eyedropper":
- const x = e.clientX - canvas.getBoundingClientRect().left;
- const y = e.clientY - canvas.getBoundingClientRect().top;
- const imageData = ctx.getImageData(x, y, 1, 1);
- const [r, g, b, a] = imageData.data;
- if (a !== 0) { // Ignorer les pixels transparents
- const selectedColor = `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;
- // Mettre à jour la valeur du color picker
- document.getElementById('colorPicker').value = selectedColor;
- // Mettre à jour la couleur de remplissage du contexte
- ctx.fillStyle = selectedColor;
- console.log("Couleur sélectionnée:", selectedColor);
- }
- break;
- }
- });
- function colorsMatch(a, b) {
- return a[0] === b[0] && a[1] === b[1] && a[2] === b[2];
- }
- function hexToRgb(hex) {
- const bigint = parseInt(hex.slice(1), 16);
- const r = (bigint >> 16) & 255;
- const g = (bigint >> 8) & 255;
- const b = bigint & 255;
- return [r, g, b];
- }
- function floodFill(startX, startY, fillColor) {
- const targetColor = ctx.getImageData(startX, startY, 1, 1).data;
- const pixels = ctx.getImageData(0, 0, canvas.width, canvas.height);
- const stack = [[startX, startY]];
- function matchTargetColor(pixelPos) {
- const r = pixels.data[pixelPos];
- const g = pixels.data[pixelPos + 1];
- const b = pixels.data[pixelPos + 2];
- const a = pixels.data[pixelPos + 3];
- return (r === targetColor[0] && g === targetColor[1] && b === targetColor[2] && a === targetColor[3]);
- }
- while (stack.length) {
- const [x, y] = stack.pop();
- if (x >= 0 && x < canvas.width && y >= 0 && y < canvas.height) {
- const pixelPos = (y * canvas.width + x) * 4;
- if (matchTargetColor(pixelPos)) {
- pixels.data[pixelPos] = fillColor[0];
- pixels.data[pixelPos + 1] = fillColor[1];
- pixels.data[pixelPos + 2] = fillColor[2];
- pixels.data[pixelPos + 3] = 255; // Assuming full opacity
- stack.push([x + 1, y]);
- stack.push([x - 1, y]);
- stack.push([x, y + 1]);
- stack.push([x, y - 1]);
- }
- }
- }
- ctx.putImageData(pixels, 0, 0);
- }
- function saveCanvas() {
- let dataURL = canvas.toDataURL('image/png');
- let link = document.createElement('a');
- link.href = dataURL;
- link.download = 'canvas.png';
- link.click();
- }
- function loadImage(event) {
- let file = event.target.files[0];
- if (file) {
- let reader = new FileReader();
- reader.onload = function(event) {
- let img = new Image();
- img.onload = function() {
- // Mettez à jour les dimensions du canvas
- canvas.width = img.width;
- canvas.height = img.height;
- ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
- finalizeDrawing();
- }
- img.src = event.target.result;
- }
- reader.readAsDataURL(file);
- }
- }
- function resetCanvas() {
- saveToHistory();
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- tempCtx.clearRect(0, 0, canvas.width, canvas.height);
- }
- function undo() {
- if (historyIndex > 0) {
- historyIndex--;
- tempCtx.putImageData(history[historyIndex], 0, 0);
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- ctx.drawImage(tempCanvas, 0, 0);
- }
- }
- function finalizeDrawing() {
- tempCtx.clearRect(0, 0, canvas.width, canvas.height);
- tempCtx.drawImage(canvas, 0, 0);
- }
- canvas.addEventListener('touchstart', (e) => {
- saveToHistory();
- isDrawing = true;
- e.preventDefault();
- let touch = e.touches[0];
- if (document.getElementById('lastPoint').checked && lastPoint) {
- startPoint = lastPoint;
- } else {
- startPoint = getAdjustedMousePos(touch);
- }
- });
- canvas.addEventListener('touchmove', (e) => {
- e.preventDefault();
- draw(e.touches[0]);
- });
- canvas.addEventListener('touchend', (e) => {
- isDrawing = false;
- let touch = e.changedTouches[0];
- draw(touch);
- lastPoint = getAdjustedMousePos(touch);
- finalizeDrawing();
- });
- //document.getElementById('drawText').addEventListener('input', placeText);
- window.onload = function() {
- let userAgent = navigator.userAgent || navigator.vendor || window.opera;
- if (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) {
- document.getElementById('paint').innerText = "Paint pour iPhone/iPad/iPod";
- } else if (/android/i.test(userAgent)) {
- document.getElementById('paint').innerText = "Paint pour Android";
- } else if (/Windows/.test(userAgent) && ('ontouchstart' in window || navigator.maxTouchPoints)) {
- document.getElementById('paint').innerText = "Paint pour Windows (Tactile)";
- } else {
- document.getElementById('paint').innerText = "Paint pour autres plateformes";
- }
- }
- </script>
- </body>
- </html>
Add Comment
Please, Sign In to add comment