<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- MODIFICAR: Título de la pestaña del navegador -->
<title>Corazón con Efecto Pincel y Tinta</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="controls">
<!-- MODIFICAR: Texto de la etiqueta para el selector de color -->
<label for="colorPicker">Color de Pintura:</label>
<!-- MODIFICAR: Color de pintura inicial -->
<input type="color" id="colorPicker" value="#ff0055">
<!-- MODIFICAR: Texto del botón para redibujar -->
<button id="redrawButton">Dibujar de Nuevo</button>
</div>
<canvas id="canvas"></canvas>
<script src="script.js"></script>
</body>
</html>
/* MODIFICAR: Estilos del fondo principal de la página */
body {
margin: 0;
background-color: #fefaf5;
background-image: url('https://www.transparenttextures.com/patterns/rice-paper-3.png');
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
overflow: hidden;
font-family: sans-serif;
}
canvas {
position: absolute;
top: 0;
left: 0;
}
/* MODIFICAR: Estilos del panel de controles (fondo, borde, sombra) */
#controls {
position: absolute;
top: 20px;
right: 20px;
background-color: rgba(250, 240, 230, 0.85);
border: 1px solid #c9bbae;
border-radius: 8px;
padding: 15px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
gap: 10px;
z-index: 10;
}
#controls label {
font-size: 14px;
color: #5a3f2e;
font-weight: bold;
}
#colorPicker {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
width: 100%;
height: 35px;
background-color: transparent;
border: 1px solid #bba89b;
border-radius: 5px;
cursor: pointer;
}
#colorPicker::-webkit-color-swatch {
border-radius: 4px;
border: none;
}
#colorPicker::-moz-color-swatch {
border-radius: 4px;
border: none;
}
/* MODIFICAR: Estilos del botón de redibujar (colores, fuente) */
#redrawButton {
padding: 10px 15px;
font-size: 16px;
background-color: #5a3f2e;
color: #fefaf5;
border: none;
border-radius: 8px;
cursor: pointer;
transition: background-color 0.3s;
width: 100%;
}
#redrawButton:hover {
background-color: #8a6b54;
}
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const redrawButton = document.getElementById('redrawButton');
const colorPicker = document.getElementById('colorPicker');
let animationFrameId;
let scale;
let paintColor = colorPicker.value;
// MODIFICAR: Límite de mensajes que se pueden escribir en el lienzo.
const MAX_MESSAGES = 10;
// MODIFICAR: Lista de mensajes de amor que aparecen al hacer clic.
const loveMessages = [
"Te Amo", "Mi Amor", "Para Siempre", "Eres mi Sol",
"Contigo todo", "Mi corazón es tuyo", "Juntos"
];
let messageIndex = 0;
let messageCount = 0;
function hexToRgb(hex) {
let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
const heartPath = (t, scale) => {
const x = 16 * Math.pow(Math.sin(t), 3);
const y = -(13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t));
return { x: x * scale + canvas.width / 2, y: y * scale + canvas.height / 2.5 };
};
let t = 0;
const maxT = Math.PI * 2;
const droplets = [];
function drawBrushStroke(x, y, isStatic = false, isText = false) {
const radius = isText ? (Math.random() * 1.5 + 0.5) : (Math.random() * 4 + 2);
const alpha = Math.random() * 0.2 + 0.3;
const dx = Math.random() * 10 - 5;
const dy = Math.random() * 10 - 5;
const px = x + dx;
const py = y + dy;
const rgbColor = hexToRgb(paintColor);
ctx.beginPath();
ctx.fillStyle = `rgba(${rgbColor.r}, ${rgbColor.g}, ${rgbColor.b}, ${alpha})`;
ctx.arc(px, py, radius, 0, Math.PI * 2);
ctx.fill();
droplets.push({ x: px, y: py, r: radius * 0.6, alpha, isStatic: isStatic, color: rgbColor });
}
function drawPaintedText(text, x, y) {
const fontSize = scale * 3;
const rgbColor = hexToRgb(paintColor);
// MODIFICAR: Fuente y estilo del texto pintado.
ctx.font = `bold ${fontSize}px 'Brush Script MT', cursive`;
ctx.fillStyle = `rgba(${rgbColor.r}, ${rgbColor.g}, ${rgbColor.b}, 0.9)`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.shadowColor = 'rgba(0, 0, 0, 0.3)';
ctx.shadowBlur = 5;
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.fillText(text, x, y);
ctx.shadowColor = 'transparent';
ctx.shadowBlur = 0;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
const metrics = ctx.measureText(text);
const textWidth = metrics.width;
const numDrips = Math.floor(text.length * 2.5);
for (let i = 0; i < numDrips; i++) {
const dripX = (x - textWidth / 2) + (Math.random() * textWidth);
const dripY = y + (Math.random() * (fontSize * 0.7));
droplets.push({
x: dripX, y: dripY, r: Math.random() * 2.5 + 1,
alpha: Math.random() * 0.4 + 0.5, isStatic: false, color: rgbColor
});
}
}
function updateDroplets() {
for (let i = droplets.length - 1; i >= 0; i--) {
const drop = droplets[i];
if (!drop.isStatic) {
// MODIFICAR: Velocidad de goteo de la pintura. Mayor es más rápido.
drop.y += 0.5 + Math.random() * 0.5;
}
drop.alpha *= 0.99;
ctx.beginPath();
ctx.fillStyle = `rgba(${drop.color.r}, ${drop.color.g}, ${drop.color.b}, ${drop.alpha})`;
ctx.arc(drop.x, drop.y, drop.r, 0, Math.PI * 2);
ctx.fill();
if (drop.alpha < 0.01) {
droplets.splice(i, 1);
}
}
}
function animate() {
animationFrameId = requestAnimationFrame(animate);
if (t <= maxT) {
const point = heartPath(t, scale);
drawBrushStroke(point.x, point.y);
// MODIFICAR: Velocidad a la que se dibuja el corazón. Mayor es más rápido.
t += 0.02;
}
updateDroplets();
}
function setupCanvas() {
if (animationFrameId) {
cancelAnimationFrame(animationFrameId);
}
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
scale = Math.min(canvas.width, canvas.height) / 45;
ctx.clearRect(0, 0, canvas.width, canvas.height);
t = 0;
droplets.length = 0;
messageCount = 0;
animate();
}
canvas.addEventListener('click', (event) => {
if (messageCount < MAX_MESSAGES) {
const message = loveMessages[messageIndex];
drawPaintedText(message, event.clientX, event.clientY);
messageIndex = (messageIndex + 1) % loveMessages.length;
messageCount++;
} else {
console.log("Límite de mensajes alcanzado. Presiona 'Dibujar de Nuevo' para limpiar.");
}
});
colorPicker.addEventListener('input', (event) => {
paintColor = event.target.value;
});
redrawButton.addEventListener('click', setupCanvas);
window.addEventListener('resize', setupCanvas);
setupCanvas();