Estoy tratando de replicar el ícono animado que mapbox tiene aquí https://docs.mapbox.com/mapbox-gl-js/example/add-image-animated/
Excepto que quiero tener una imagen para el círculo interior.
Hasta ahora puedo acercarme bastante usando un patrón de creación como el anterior. Pero la imagen se repite en lugar de estar centrada en el círculo interior.
¿Cómo puedo recortar mi imagen y centrarla en el círculo interior?
// Copy pasta from mapbox example ... // Draw the outer circle. context.clearRect(0, 0, this.width, this.height) context.beginPath() context.arc(this.width / 2, this.height / 2, outerRadius, 0, Math.PI * 2) context.fillStyle = `hsl(46deg 85% 67% / ${1 - t})` context.fill() // Draw the inner circle. context.beginPath() context.arc(this.width / 2, this.height / 2, radius, 0, Math.PI * 2) // I've added this const pattern = context.createPattern(image, 'repeat') context.fillStyle = pattern // I've tried this but the image isn't cropped and isn't centered. // context.drawImage(image, this.width / 2, this.height / 2, 150, 150) context.strokeStyle = 'white' context.lineWidth = 2 + 4 * (1 - t) context.fill() context.stroke()
De hecho, creo que ya casi llegaste.
Como no desea que se repita, primero configure el patrón para que no se repita:
const pattern = ctx.createPattern(img, 'no-repeat');
El cálculo de relleno de patrón comienza en la esquina superior izquierda ( 0, 0
), por lo que solo no lo hará. Tendremos que transformar el patrón también:
pattern.setTransform( new DOMMatrix( [ // No rotation, 1-1 scale 1, 0, 0, 1, // Translate to center, offset by half-image canvas.width / 2 - img.width / 2, canvas.height / 2 - img.height / 2 ]) );
Documentos:
Aquí hay una demostración de cómo usarlo. No pude hacer funcionar su demostración de CodePen, así que tuve que basarme en eso e improvisar un poco:
const canvas = document.querySelector('canvas'); const ctx = canvas.getContext('2d'); const size = 300; const img = new Image(); img.src = 'https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle/canvas_fillstyle.png'; img.onload = function() { const pattern = ctx.createPattern(img, 'no-repeat'); const radius = (size / 2) * 0.3; const outerRadius = (size / 2) * 0.7 + radius; ctx.fillStyle = `hsl(46deg 85% 67% / ${0})`; ctx.arc(canvas.width / 2, canvas.height / 2, outerRadius, 0, Math.PI * 2); ctx.fill(); ctx.beginPath(); ctx.arc(canvas.width / 2, canvas.height / 2, radius, 0, Math.PI * 2); pattern.setTransform(new DOMMatrix([1, 0, 0, 1, canvas.width / 2 - img.width / 2, canvas.height / 2 - img.height / 2])); ctx.fillStyle = pattern; ctx.strokeStyle = 'white'; ctx.lineWidth = 2; ctx.fill(); ctx.stroke(); };
canvas { border: 1px solid black; background-color: gray; }
<canvas width="400" height="400"></canvas> <div>For reference, here's the original image:</div> <img src="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle/canvas_fillstyle.png" />