About drug abuse make a animated video

Asking for Preferences

What kind of animated video output would you like? · Who is the target audience?

Animation video video

I'll create an animated HTML5 video about drug abuse that you can play directly in your browser. Let me build it now.
Running Command

mkdir -p /home/daytona/workspace/drug-abuse-animation

Writing File

~/drug-abuse-animation/index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Drug Abuse Awareness – Animated Story</title>
<style>
  * { margin: 0; padding: 0; box-sizing: border-box; }
  body { background: #0a0a1a; font-family: 'Segoe UI', sans-serif; display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 100vh; }

  h1 { color: #fff; font-size: 1.3rem; letter-spacing: 2px; text-transform: uppercase; margin-bottom: 12px; opacity: 0.7; }

  #stage {
    width: 800px; height: 450px;
    border-radius: 18px;
    overflow: hidden;
    position: relative;
    box-shadow: 0 0 60px rgba(100,60,200,0.5);
    background: #111;
  }

  canvas { display: block; }

  #controls {
    margin-top: 18px;
    display: flex; gap: 14px; align-items: center;
  }
  button {
    padding: 10px 28px; border: none; border-radius: 30px;
    background: linear-gradient(135deg,#7b2ff7,#f107a3);
    color: #fff; font-size: 1rem; cursor: pointer;
    letter-spacing: 1px; transition: opacity .2s;
  }
  button:hover { opacity: .85; }

  #scene-label {
    color: #ccc; font-size: .85rem; letter-spacing: 1px;
    min-width: 180px; text-align: center;
  }

  #progress-bar-wrap {
    width: 800px; height: 6px; background: #222; border-radius: 3px; margin-top: 10px;
  }
  #progress-bar {
    height: 100%; border-radius: 3px;
    background: linear-gradient(90deg,#7b2ff7,#f107a3);
    width: 0%; transition: width .3s;
  }
</style>
</head>
<body>
<h1>🎬 Drug Abuse Awareness</h1>
<div id="stage"><canvas id="c" width="800" height="450"></canvas></div>
<div id="progress-bar-wrap"><div id="progress-bar"></div></div>
<div id="controls">
  <button id="playBtn">▶ Play</button>
  <span id="scene-label">Scene 1 / 8</span>
  <button id="restartBtn">↺ Restart</button>
</div>

<script>
// ─── Canvas & context ────────────────────────────────────────────────────────
const canvas = document.getElementById('c');
const ctx = canvas.getContext('2d');
const W = canvas.width, H = canvas.height;

// ─── Utility helpers ─────────────────────────────────────────────────────────
function lerp(a,b,t){ return a+(b-a)*t; }
function easeInOut(t){ return t<.5?2*t*t:1-Math.pow(-2*t+2,2)/2; }
function easeOut(t){ return 1-Math.pow(1-t,3); }

// ─── Drawing primitives ──────────────────────────────────────────────────────
function drawSky(y1col, y2col){
  const g=ctx.createLinearGradient(0,0,0,H);
  g.addColorStop(0,y1col); g.addColorStop(1,y2col);
  ctx.fillStyle=g; ctx.fillRect(0,0,W,H);
}

function drawGround(y, col){
  ctx.fillStyle=col; ctx.fillRect(0,y,W,H-y);
}

function drawCloud(x,y,s,a){
  ctx.save(); ctx.globalAlpha=a;
  ctx.fillStyle='#fff';
  [[0,0,s],[s*.6,s*.1,s*.7],[s*1.2,0,s*.8],[s*.3,-s*.4,s*.6],[s*.9,-s*.35,s*.55]].forEach(([dx,dy,r])=>{
    ctx.beginPath(); ctx.arc(x+dx,y+dy,r,0,Math.PI*2); ctx.fill();
  });
  ctx.restore();
}

function drawStar(x,y,r,a){
  ctx.save(); ctx.globalAlpha=a;
  ctx.fillStyle='#fff'; ctx.beginPath(); ctx.arc(x,y,r,0,Math.PI*2); ctx.fill();
  ctx.restore();
}

// Draw a simple stick-person (x,y = feet center)
function drawPerson(x, y, scale, opts={}){
  const {
    shirtColor='#3498db', pantsColor='#2c3e50', skinColor='#f5cba7',
    happy=true, sweat=false, flipped=false, alpha=1
  } = opts;
  ctx.save();
  ctx.globalAlpha=alpha;
  if(flipped){ ctx.translate(x,y); ctx.scale(-1,1); ctx.translate(-x,-y); }

  const S=scale;
  // Legs
  ctx.strokeStyle=pantsColor; ctx.lineWidth=S*3;
  ctx.beginPath(); ctx.moveTo(x,y-S*30); ctx.lineTo(x-S*12,y); ctx.stroke();
  ctx.beginPath(); ctx.moveTo(x,y-S*30); ctx.lineTo(x+S*12,y); ctx.stroke();
  // Body
  ctx.strokeStyle=shirtColor; ctx.lineWidth=S*4;
  ctx.beginPath(); ctx.moveTo(x,y-S*65); ctx.lineTo(x,y-S*30); ctx.stroke();
  // Arms
  ctx.strokeStyle=shirtColor; ctx.lineWidth=S*3;
  if(happy){
    ctx.beginPath(); ctx.moveTo(x,y-S*55); ctx.lineTo(x-S*20,y-S*40); ctx.stroke();
    ctx.beginPath(); ctx.moveTo(x,y-S*55); ctx.lineTo(x+S*20,y-S*40); ctx.stroke();
  } else {
    ctx.beginPath(); ctx.moveTo(x,y-S*55); ctx.lineTo(x-S*18,y-S*65); ctx.stroke();
    ctx.beginPath(); ctx.moveTo(x,y-S*55); ctx.lineTo(x+S*18,y-S*65); ctx.stroke();
  }
  // Head
  ctx.fillStyle=skinColor; ctx.beginPath(); ctx.arc(x,y-S*80,S*15,0,Math.PI*2); ctx.fill();
  ctx.strokeStyle='#c8a07a'; ctx.lineWidth=1; ctx.stroke();
  // Eyes
  ctx.fillStyle='#222';
  ctx.beginPath(); ctx.arc(x-S*5,y-S*82,S*2.5,0,Math.PI*2); ctx.fill();
  ctx.beginPath(); ctx.arc(x+S*5,y-S*82,S*2.5,0,Math.PI*2); ctx.fill();
  // Mouth
  ctx.strokeStyle='#a0522d'; ctx.lineWidth=S*1.5;
  ctx.beginPath();
  if(happy){
    ctx.arc(x,y-S*76,S*6,0.2,Math.PI-0.2); ctx.stroke();
  } else {
    ctx.arc(x,y-S*70,S*6,Math.PI+0.2,-0.2); ctx.stroke();
  }
  // Sweat drops
  if(sweat){
    ctx.fillStyle='#74b9ff';
    ctx.beginPath(); ctx.arc(x+S*18,y-S*85,S*3,0,Math.PI*2); ctx.fill();
    ctx.beginPath(); ctx.arc(x+S*22,y-S*78,S*2,0,Math.PI*2); ctx.fill();
  }
  ctx.restore();
}

function drawBrain(x,y,s,col,a){
  ctx.save(); ctx.globalAlpha=a;
  ctx.fillStyle=col; ctx.strokeStyle='#8e44ad'; ctx.lineWidth=2;
  ctx.beginPath();
  ctx.ellipse(x,y,s*1.1,s*.8,0,0,Math.PI*2); ctx.fill(); ctx.stroke();
  ctx.fillStyle='rgba(0,0,0,.15)';
  // folds
  for(let i=0;i<5;i++){
    ctx.beginPath();
    ctx.arc(x-s*.5+i*s*.25,y,s*.3,0,Math.PI,true);
    ctx.stroke();
  }
  ctx.restore();
}

function drawPill(x,y,w,h,col,a){
  ctx.save(); ctx.globalAlpha=a;
  ctx.fillStyle=col; ctx.strokeStyle='rgba(0,0,0,.2)'; ctx.lineWidth=2;
  ctx.beginPath();
  const r=h/2;
  ctx.moveTo(x+r,y); ctx.lineTo(x+w-r,y);
  ctx.arc(x+w-r,y+r,r,-Math.PI/2,Math.PI/2);
  ctx.lineTo(x+r,y+h);
  ctx.arc(x+r,y+r,r,Math.PI/2,3*Math.PI/2);
  ctx.closePath(); ctx.fill(); ctx.stroke();
  ctx.restore();
}

function drawSyringe(x,y,angle,a){
  ctx.save(); ctx.globalAlpha=a;
  ctx.translate(x,y); ctx.rotate(angle);
  ctx.fillStyle='#ecf0f1'; ctx.strokeStyle='#bdc3c7'; ctx.lineWidth=2;
  ctx.fillRect(-40,-8,80,16); ctx.strokeRect(-40,-8,80,16);
  ctx.fillStyle='#c0392b';
  ctx.fillRect(-40,-8,30,16);
  ctx.fillStyle='#7f8c8d';
  ctx.beginPath(); ctx.moveTo(40,-4); ctx.lineTo(60,0); ctx.lineTo(40,4); ctx.closePath(); ctx.fill();
  ctx.restore();
}

function drawCross(x,y,s,col,a){
  ctx.save(); ctx.globalAlpha=a;
  ctx.fillStyle=col;
  ctx.fillRect(x-s*.15,y-s*.5,s*.3,s);
  ctx.fillRect(x-s*.5,y-s*.15,s,s*.3);
  ctx.restore();
}

function drawHeart(x,y,s,col,a){
  ctx.save(); ctx.globalAlpha=a;
  ctx.fillStyle=col;
  ctx.beginPath();
  ctx.moveTo(x,y+s*.4);
  ctx.bezierCurveTo(x,y,x-s,y,x-s,y-s*.4);
  ctx.bezierCurveTo(x-s,y-s,x,y-s*.9,x,y-s*.5);
  ctx.bezierCurveTo(x,y-s*.9,x+s,y-s,x+s,y-s*.4);
  ctx.bezierCurveTo(x+s,y,x,y,x,y+s*.4);
  ctx.closePath(); ctx.fill();
  ctx.restore();
}

function drawTree(x,y,s,a){
  ctx.save(); ctx.globalAlpha=a;
  ctx.fillStyle='#5d4037'; ctx.fillRect(x-s*.08,y-s*.3,s*.16,s*.3);
  ctx.fillStyle='#2e7d32';
  ctx.beginPath(); ctx.arc(x,y-s*.5,s*.35,0,Math.PI*2); ctx.fill();
  ctx.beginPath(); ctx.arc(x-s*.2,y-s*.3,s*.25,0,Math.PI*2); ctx.fill();
  ctx.beginPath(); ctx.arc(x+s*.2,y-s*.3,s*.25,0,Math.PI*2); ctx.fill();
  ctx.restore();
}

function drawBuilding(x,y,w,h,col,a){
  ctx.save(); ctx.globalAlpha=a;
  ctx.fillStyle=col;
  ctx.fillRect(x,y,w,h);
  ctx.fillStyle='rgba(255,255,180,0.6)';
  for(let row=0;row<4;row++) for(let col2=0;col2<3;col2++){
    ctx.fillRect(x+8+col2*(w/3.2), y+10+row*((h-10)/4.5), w/5, h/7);
  }
  ctx.restore();
}

function writeText(text, x, y, size, col, align, bold, alpha){
  ctx.save();
  ctx.globalAlpha = alpha !== undefined ? alpha : 1;
  ctx.fillStyle=col;
  ctx.font = `${bold?'bold ':''}${size}px Segoe UI, Arial`;
  ctx.textAlign=align||'center';
  ctx.fillText(text, x, y);
  ctx.restore();
}

function wrapText(text, x, y, maxW, lineH, size, col, alpha){
  ctx.save();
  ctx.globalAlpha = alpha !== undefined ? alpha : 1;
  ctx.fillStyle=col;
  ctx.font=`${size}px Segoe UI, Arial`;
  ctx.textAlign='center';
  const words=text.split(' '), lines=[];
  let cur='';
  words.forEach(w=>{
    const test=cur?cur+' '+w:w;
    if(ctx.measureText(test).width>maxW){ lines.push(cur); cur=w; }
    else cur=test;
  });
  lines.push(cur);
  lines.forEach((l,i)=>ctx.fillText(l,x,y+i*lineH));
  ctx.restore();
}

function drawSubtitleBox(text, progress){
  if(!text) return;
  ctx.save();
  ctx.fillStyle='rgba(0,0,0,0.6)';
  ctx.beginPath();
  const bw=700, bh=52, bx=(W-bw)/2, by=H-75;
  ctx.roundRect(bx,by,bw,bh,10);
  ctx.fill();
  ctx.fillStyle='#fff';
  ctx.font='bold 18px Segoe UI, Arial';
  ctx.textAlign='center';
  ctx.fillText(text, W/2, by+34);
  ctx.restore();
}

// ─── Stars (for night scenes) ─────────────────────────────────────────────
const stars = Array.from({length:80},()=>({
  x:Math.random()*W, y:Math.random()*H*.5,
  r:Math.random()*1.5+0.3, twinkle:Math.random()*Math.PI*2
}));
function drawStars(t){
  stars.forEach(s=>{
    drawStar(s.x,s.y,s.r,(Math.sin(s.twinkle+t*.02)*.3+.7)*.8);
  });
}

// ─── Particle system ─────────────────────────────────────────────────────────
class Particle {
  constructor(x,y,vx,vy,col,life,r){
    this.x=x;this.y=y;this.vx=vx;this.vy=vy;
    this.col=col;this.life=life;this.maxLife=life;this.r=r;
  }
  update(){
    this.x+=this.vx; this.y+=this.vy;
    this.vy+=.15; this.life--;
  }
  draw(){
    const a=this.life/this.maxLife;
    ctx.save(); ctx.globalAlpha=a;
    ctx.fillStyle=this.col;
    ctx.beginPath(); ctx.arc(this.x,this.y,this.r,0,Math.PI*2); ctx.fill();
    ctx.restore();
  }
}
let particles = [];
function spawnParticles(x,y,col,n,speed,life,r){
  for(let i=0;i<n;i++){
    const angle=Math.random()*Math.PI*2;
    const v=Math.random()*speed+1;
    particles.push(new Particle(x,y,Math.cos(angle)*v,Math.sin(angle)*v-2,col,life,r||4));
  }
}

// ─── Scene definitions ───────────────────────────────────────────────────────
// Each scene: { duration (frames), draw(t, progress 0-1) }
const SCENES = [

  // ── Scene 0: Title ──────────────────────────────────────────────────────
  {
    duration: 180,
    subtitle: 'Drug Abuse: Know the Truth',
    draw(t, p){
      drawSky('#0d1b2a','#1a3a5c');
      drawStars(t);
      // big glowing title
      const pulse = Math.sin(t*.05)*.05+.95;
      ctx.save();
      ctx.shadowColor='#f107a3'; ctx.shadowBlur=30;
      writeText('DRUG ABUSE', W/2, H/2-40, 72*pulse, '#fff', 'center', true, easeOut(p));
      ctx.shadowColor='#7b2ff7'; ctx.shadowBlur=20;
      writeText('KNOW THE TRUTH', W/2, H/2+30, 30, '#f1c40f', 'center', true, easeOut(Math.max(0,p-.3)/.7));
      ctx.restore();
      writeText('An Awareness Story', W/2, H/2+80, 20, '#aaa', 'center', false, easeOut(Math.max(0,p-.6)/.4));
      // floating pills
      for(let i=0;i<4;i++){
        const px=100+i*190, py=60+Math.sin(t*.03+i)*15;
        drawPill(px,py,50,20,['#e74c3c','#3498db','#2ecc71','#f39c12'][i],0.3);
      }
    }
  },

  // ── Scene 1: Happy life ──────────────────────────────────────────────────
  {
    duration: 200,
    subtitle: 'Alex was a happy, healthy student with big dreams.',
    draw(t, p){
      // daytime sky
      drawSky('#87ceeb','#c9e8ff');
      // sun
      ctx.save(); ctx.shadowColor='#ffeb3b'; ctx.shadowBlur=40;
      ctx.fillStyle='#ffeb3b'; ctx.beginPath(); ctx.arc(680,80,45,0,Math.PI*2); ctx.fill();
      ctx.restore();
      drawCloud(80,80,.4,0.85);
      drawCloud(400,60,.5,0.7);
      drawGround(320,'#4caf50');
      // school building
      drawBuilding(120, 180, 180, 140, '#ecf0f1', easeOut(p));
      writeText('SCHOOL', 210, 240, 16, '#34495e', 'center', true, easeOut(p));
      // trees
      drawTree(360, 320, 80, easeOut(p));
      drawTree(420, 320, 60, easeOut(p));
      // happy Alex walking in
      const alexX = lerp(-60, 260, easeInOut(Math.min(1, p*2)));
      drawPerson(alexX, 320, 1.6, {happy:true, shirtColor:'#3498db', alpha:easeOut(p)});
      // school bag (simple rect)
      ctx.save(); ctx.globalAlpha=easeOut(p);
      ctx.fillStyle='#e74c3c';
      ctx.fillRect(alexX+12, 320-85, 20, 28); ctx.restore();
      // birds
      for(let b=0;b<3;b++){
        const bx=(200+b*120+t*.8)%820-20;
        const by=100+b*20+Math.sin(t*.06+b)*8;
        ctx.save(); ctx.strokeStyle='#333'; ctx.lineWidth=2;
        ctx.beginPath(); ctx.moveTo(bx,by); ctx.quadraticCurveTo(bx+8,by-6,bx+16,by); ctx.stroke();
        ctx.restore();
      }
    }
  },

  // ── Scene 2: Peer pressure ──────────────────────────────────────────────
  {
    duration: 220,
    subtitle: 'One day, a friend offered Alex a drug — "Just try it once!"',
    draw(t, p){
      drawSky('#2c3e50','#4a235a');
      drawGround(330,'#1a1a1a');
      drawStars(t);
      // street lamp
      ctx.save(); ctx.strokeStyle='#f39c12'; ctx.lineWidth=4;
      ctx.beginPath(); ctx.moveTo(600,100); ctx.lineTo(600,330); ctx.stroke();
      ctx.fillStyle='#f1c40f'; ctx.beginPath(); ctx.ellipse(600,105,20,8,0,0,Math.PI*2); ctx.fill();
      ctx.save(); ctx.shadowColor='#f1c40f'; ctx.shadowBlur=40;
      ctx.fillStyle='rgba(255,240,100,0.12)';
      ctx.beginPath(); ctx.ellipse(600,220,100,200,0,0,Math.PI*2); ctx.fill();
      ctx.restore(); ctx.restore();
      // Alex (nervous)
      const alexX = 320;
      drawPerson(alexX, 330, 1.6, {happy:false, shirtColor:'#3498db', sweat:true, alpha:easeOut(p)});
      // Bad friend
      const friendX = lerp(800, 500, easeInOut(Math.min(1,p*1.5)));
      drawPerson(friendX, 330, 1.6, {happy:true, shirtColor:'#e74c3c', skinColor:'#f5cba7', flipped:true, alpha:easeOut(p)});
      // pill/offer floating
      if(p > .4){
        const pillA = easeOut((p-.4)/.6);
        drawPill(alexX+80, 280, 50, 20, '#e74c3c', pillA);
        writeText('Try it!', alexX+130, 265, 18, '#f1c40f', 'center', true, pillA);
        // question mark over Alex
        writeText('?', alexX-10, 235, 36, '#fff', 'center', true, pillA*.8);
      }
      // speech bubble from friend
      if(p > .5){
        const bx=friendX-120, by=230;
        ctx.save(); ctx.globalAlpha=easeOut((p-.5)/.5);
        ctx.fillStyle='#fff'; ctx.strokeStyle='#ccc'; ctx.lineWidth=2;
        ctx.beginPath(); ctx.roundRect(bx-70,by-25,150,45,12); ctx.fill(); ctx.stroke();
        ctx.beginPath(); ctx.moveTo(bx+30,by+20); ctx.lineTo(bx+50,by+42); ctx.lineTo(bx+15,by+20); ctx.closePath(); ctx.fill();
        writeText('Just once!', bx+5, by+3, 16, '#c0392b', 'center', true);
        ctx.restore();
      }
    }
  },

  // ── Scene 3: Brain effect ───────────────────────────────────────────────
  {
    duration: 220,
    subtitle: 'Drugs flood the brain with dopamine — creating a false sense of pleasure.',
    draw(t, p){
      drawSky('#1a0033','#330055');
      // Brain center stage
      const bx=W/2, by=H/2-20;
      const bs=90+Math.sin(t*.08)*8;
      // glow
      ctx.save();
      ctx.shadowColor='#9b59b6'; ctx.shadowBlur=50+Math.sin(t*.06)*20;
      drawBrain(bx, by, bs, '#e8b4f8', easeOut(p));
      ctx.restore();
      writeText('BRAIN', bx, by+bs+20, 18, '#ddd', 'center', true, easeOut(p));
      // dopamine particles
      if(p>.3){
        const dp=easeOut((p-.3)/.7);
        for(let i=0;i<8;i++){
          const angle=(i/8)*Math.PI*2+t*.04;
          const r=120+Math.sin(t*.05+i)*15;
          const px2=bx+Math.cos(angle)*r, py2=by+Math.sin(angle)*r;
          ctx.save(); ctx.globalAlpha=dp;
          ctx.fillStyle='#f1c40f';
          ctx.font='bold 22px Arial';
          ctx.textAlign='center';
          ctx.fillText('✦', px2, py2);
          ctx.restore();
        }
        // dopamine label
        writeText('DOPAMINE SURGE', W/2, 60, 24, '#f1c40f', 'center', true, dp);
        // arrows into brain
        for(let i=0;i<5;i++){
          const angle=(i/5)*Math.PI*2+t*.02;
          const x1=bx+Math.cos(angle)*(bs+80);
          const y1=by+Math.sin(angle)*(bs+80);
          const x2=bx+Math.cos(angle)*bs;
          const y2=by+Math.sin(angle)*bs;
          ctx.save(); ctx.globalAlpha=dp*.7;
          ctx.strokeStyle='#9b59b6'; ctx.lineWidth=3;
          ctx.beginPath(); ctx.moveTo(x1,y1); ctx.lineTo(x2,y2); ctx.stroke();
          ctx.fillStyle='#9b59b6';
          ctx.beginPath(); ctx.arc(x2,y2,5,0,Math.PI*2); ctx.fill();
          ctx.restore();
        }
      }
      // Warning note
      if(p>.6){
        const wa=easeOut((p-.6)/.4);
        ctx.save(); ctx.globalAlpha=wa;
        ctx.fillStyle='rgba(231,76,60,0.2)';
        ctx.beginPath(); ctx.roundRect(30,H-130,W-60,70,10); ctx.fill();
        wrapText('Over time the brain needs MORE drug to feel normal — this is ADDICTION',
          W/2, H-100, 700, 24, 16, '#ff7675', wa);
        ctx.restore();
      }
    }
  },

  // ── Scene 4: Downward spiral ─────────────────────────────────────────────
  {
    duration: 240,
    subtitle: 'Alex started skipping school, losing friends, and falling apart.',
    draw(t, p){
      // gloomy sky
      drawSky('#2d3436','#636e72');
      drawGround(320,'#555');
      // rain
      for(let r=0;r<40;r++){
        const rx=(r*97+t*4)%W;
        const ry=((r*73+t*6))%(H*.8);
        ctx.save(); ctx.globalAlpha=.3;
        ctx.strokeStyle='#74b9ff'; ctx.lineWidth=1;
        ctx.beginPath(); ctx.moveTo(rx,ry); ctx.lineTo(rx-3,ry+15); ctx.stroke();
        ctx.restore();
      }
      // crumbling house
      const cx=130;
      ctx.save(); ctx.globalAlpha=easeOut(p);
      ctx.fillStyle='#795548';
      ctx.fillRect(cx,180,140,140);
      ctx.fillStyle='#5d4037';
      ctx.beginPath(); ctx.moveTo(cx-10,180); ctx.lineTo(cx+70,120); ctx.lineTo(cx+150,180); ctx.closePath(); ctx.fill();
      // cracks
      ctx.strokeStyle='#212121'; ctx.lineWidth=2;
      ctx.beginPath(); ctx.moveTo(cx+40,200); ctx.lineTo(cx+55,240); ctx.lineTo(cx+48,270); ctx.stroke();
      ctx.beginPath(); ctx.moveTo(cx+90,190); ctx.lineTo(cx+80,220); ctx.stroke();
      ctx.restore();
      // Alex sad, hunched
      const alexX = 360;
      // hunched by lowering y and making sad
      drawPerson(alexX, 320 + Math.sin(t*.03)*3, 1.4, {
        happy:false, shirtColor:'#636e72', sweat:false, alpha:easeOut(p)
      });
      // broken items around Alex
      if(p>.3){
        const ia=easeOut((p-.3)/.7);
        // broken phone
        ctx.save(); ctx.globalAlpha=ia;
        ctx.fillStyle='#333'; ctx.fillRect(alexX+25, 285, 22, 36);
        ctx.strokeStyle='#e74c3c'; ctx.lineWidth=1.5;
        ctx.beginPath(); ctx.moveTo(alexX+30,295); ctx.lineTo(alexX+43,315); ctx.stroke();
        ctx.beginPath(); ctx.moveTo(alexX+43,295); ctx.lineTo(alexX+30,315); ctx.stroke();
        ctx.restore();
        // Report card F
        ctx.save(); ctx.globalAlpha=ia;
        ctx.fillStyle='#ecf0f1'; ctx.fillRect(alexX-55, 265, 36, 45);
        writeText('F', alexX-37, 295, 26, '#e74c3c', 'center', true);
        ctx.restore();
      }
      // Crossed-out friends
      if(p>.5){
        const fa=easeOut((p-.5)/.5);
        drawPerson(580, 320, 1.2, {happy:false, shirtColor:'#aaa', alpha:fa*.4});
        drawPerson(650, 320, 1.2, {happy:false, shirtColor:'#aaa', alpha:fa*.4});
        drawCross(580, 270, 40, 'rgba(231,76,60,.7)', fa);
        drawCross(650, 270, 40, 'rgba(231,76,60,.7)', fa);
      }
      // pills on ground
      for(let i=0;i<5;i++){
        drawPill(alexX+50+i*30, 310, 28, 12, ['#e74c3c','#3498db','#9b59b6','#e74c3c','#2ecc71'][i], easeOut(p)*.6);
      }
    }
  },

  // ── Scene 5: Health consequences ────────────────────────────────────────
  {
    duration: 220,
    subtitle: 'Drug abuse destroys your body, mind, and future.',
    draw(t, p){
      drawSky('#1a1a2e','#16213e');
      // Split screen – left: body, right: stats
      // Left side: deteriorating person
      const pulse=Math.sin(t*.1)*.1;
      drawPerson(200, 340, 1.5+pulse, {
        happy:false, shirtColor:'#636e72', skinColor:'#d5a29a', sweat:true,
        alpha:easeOut(p)
      });
      // heartbeat line erratic
      ctx.save(); ctx.globalAlpha=easeOut(p);
      ctx.strokeStyle='#e74c3c'; ctx.lineWidth=2;
      ctx.beginPath();
      const hbStart=60, hbY=H-100;
      ctx.moveTo(hbStart, hbY);
      const hbData=[0,0,0,-30,30,-15,10,0,0,0,0,-5,5,0,-20,25,-10,5,0,0];
      hbData.forEach((dy,i)=>ctx.lineTo(hbStart+i*16, hbY+dy));
      ctx.stroke();
      ctx.restore();
      writeText('♥ Irregular heartbeat', 210, H-55, 14, '#ff7675', 'center', false, easeOut(p));
      // Right side consequences
      const consList = [
        {icon:'🧠', text:'Brain damage', col:'#a29bfe'},
        {icon:'💉', text:'HIV / Hepatitis risk', col:'#fd79a8'},
        {icon:'🫁', text:'Lung & liver failure', col:'#fdcb6e'},
        {icon:'💔', text:'Heart disease', col:'#e74c3c'},
        {icon:'😰', text:'Mental illness', col:'#74b9ff'},
      ];
      consList.forEach((c,i)=>{
        const cy=90+i*62, ca=easeOut(Math.max(0,(p-i*.08-.1)/.5));
        ctx.save(); ctx.globalAlpha=ca;
        ctx.fillStyle='rgba(255,255,255,.08)';
        ctx.beginPath(); ctx.roundRect(420, cy-26, 320, 50, 8); ctx.fill();
        ctx.font='22px Arial'; ctx.textAlign='left'; ctx.fillText(c.icon, 435, cy+8);
        writeText(c.text, 580, cy+8, 18, c.col, 'center', true, 1);
        ctx.restore();
      });
    }
  },

  // ── Scene 6: Help & Recovery ─────────────────────────────────────────────
  {
    duration: 220,
    subtitle: 'It is never too late. Help is available — reach out!',
    draw(t, p){
      drawSky('#0a3d62','#1e3799');
      drawGround(330,'#27ae60');
      // sunrise/hope
      const sunY=80-easeOut(p)*30;
      ctx.save(); ctx.shadowColor='#f1c40f'; ctx.shadowBlur=60;
      ctx.fillStyle='#f1c40f'; ctx.beginPath(); ctx.arc(W/2,sunY+20,50,0,Math.PI*2); ctx.fill();
      ctx.restore();
      // rays
      for(let r=0;r<12;r++){
        const angle=(r/12)*Math.PI*2+t*.01;
        ctx.save(); ctx.globalAlpha=.15*easeOut(p);
        ctx.strokeStyle='#f1c40f'; ctx.lineWidth=3;
        ctx.beginPath();
        ctx.moveTo(W/2+Math.cos(angle)*55, sunY+20+Math.sin(angle)*55);
        ctx.lineTo(W/2+Math.cos(angle)*90, sunY+20+Math.sin(angle)*90);
        ctx.stroke(); ctx.restore();
      }
      // doctor / counselor
      drawPerson(320, 330, 1.6, {happy:true, shirtColor:'#fff', skinColor:'#f5cba7', alpha:easeOut(p)});
      // stethoscope (simple arc)
      ctx.save(); ctx.globalAlpha=easeOut(p);
      ctx.strokeStyle='#3498db'; ctx.lineWidth=3;
      ctx.beginPath(); ctx.arc(320, 330-60, 18, -.5, Math.PI+.5); ctx.stroke();
      ctx.restore();
      writeText('Doctor / Counselor', 320, H-10, 15, '#aaa', 'center', false, easeOut(p));
      // Alex recovering
      const alexX=500;
      const alexY=330-easeOut(Math.max(0,p-.3)/.7)*10;
      drawPerson(alexX, alexY, 1.6, {happy: p>.5, shirtColor:'#2ecc71', alpha:easeOut(Math.max(0,p-.1)/.9)});
      // heart growing
      if(p>.4){
        const ha=easeOut((p-.4)/.6);
        drawHeart(alexX, alexY-130, 20*ha, '#e74c3c', ha);
      }
      // support sign
      if(p>.5){
        const sa=easeOut((p-.5)/.5);
        ctx.save(); ctx.globalAlpha=sa;
        ctx.fillStyle='#2ecc71'; ctx.strokeStyle='#27ae60'; ctx.lineWidth=2;
        ctx.beginPath(); ctx.roundRect(590,140,180,80,10); ctx.fill(); ctx.stroke();
        writeText('REHAB', 680, 178, 20, '#fff', 'center', true);
        writeText('We support you', 680, 205, 14, '#d5f5e3', 'center', false);
        // pole
        ctx.strokeStyle='#795548'; ctx.lineWidth=4;
        ctx.beginPath(); ctx.moveTo(680,220); ctx.lineTo(680,330); ctx.stroke();
        ctx.restore();
      }
      // falling confetti/stars (hope)
      if(p>.6){
        for(let i=0;i<15;i++){
          const cx2=(i*137.5+t*2)%W;
          const cy2=((i*83+t*3)%(H*.7));
          ctx.save(); ctx.globalAlpha=.5;
          ctx.fillStyle=['#f1c40f','#2ecc71','#3498db','#9b59b6','#e74c3c'][i%5];
          ctx.beginPath(); ctx.arc(cx2,cy2,4,0,Math.PI*2); ctx.fill();
          ctx.restore();
        }
      }
    }
  },

  // ── Scene 7: Say NO / CTA ────────────────────────────────────────────────
  {
    duration: 240,
    subtitle: 'Say NO to drugs. Choose life. Choose YOUR future.',
    draw(t, p){
      drawSky('#0d1b2a','#1a3a5c');
      drawStars(t);
      // big NO
      const noScale=easeOut(p)*1+.3;
      ctx.save();
      ctx.translate(W/2, H/2-30);
      ctx.scale(noScale, noScale);
      ctx.shadowColor='#e74c3c'; ctx.shadowBlur=50;
      ctx.fillStyle='#e74c3c';
      ctx.font='bold 110px Segoe UI, Arial';
      ctx.textAlign='center';
      ctx.fillText('SAY NO', 0, 0);
      ctx.restore();
      // to drugs
      writeText('to drugs', W/2, H/2+50, 38, '#f1c40f', 'center', true, easeOut(Math.max(0,p-.2)/.8));
      // three happy people at bottom
      if(p>.4){
        const ga=easeOut((p-.4)/.6);
        drawPerson(W/2-140, H-40, 1.5, {happy:true, shirtColor:'#3498db', alpha:ga});
        drawPerson(W/2, H-40, 1.5, {happy:true, shirtColor:'#2ecc71', alpha:ga});
        drawPerson(W/2+140, H-40, 1.5, {happy:true, shirtColor:'#9b59b6', alpha:ga});
      }
      // hotline box
      if(p>.6){
        const ha=easeOut((p-.6)/.4);
        ctx.save(); ctx.globalAlpha=ha;
        ctx.fillStyle='rgba(255,255,255,.12)';
        ctx.beginPath(); ctx.roundRect(W/2-200,H-175,400,55,10); ctx.fill();
        writeText('📞 Helpline: 1-800-662-4357 (SAMHSA)', W/2, H-142, 16, '#74b9ff', 'center', true);
        ctx.restore();
      }
      // confetti celebration
      particles.forEach(pp=>{ pp.update(); pp.draw(); });
      particles=particles.filter(pp=>pp.life>0);
      if(p>.5 && Math.random()<.4){
        const col=['#f1c40f','#2ecc71','#3498db','#e74c3c','#9b59b6'][Math.floor(Math.random()*5)];
        spawnParticles(Math.random()*W, -10, col, 2, 3, 60, 5);
      }
    }
  }
];

// ─── Animation engine ─────────────────────────────────────────────────────
let currentScene = 0;
let sceneFrame = 0;
let totalFrame = 0;
let running = false;
let animId = null;

const totalFrames = SCENES.reduce((s,sc)=>s+sc.duration, 0);

function render(){
  const scene = SCENES[currentScene];
  const progress = sceneFrame / scene.duration;
  ctx.clearRect(0,0,W,H);
  scene.draw(sceneFrame, Math.min(1, progress));
  drawSubtitleBox(scene.subtitle, progress);
  // scene number overlay
  ctx.save(); ctx.globalAlpha=.5;
  ctx.fillStyle='rgba(0,0,0,.4)';
  ctx.beginPath(); ctx.roundRect(14,14,110,30,8); ctx.fill();
  writeText(`Scene ${currentScene+1} / ${SCENES.length}`, 69, 34, 14, '#ccc', 'center', false);
  ctx.restore();
  // progress bar
  document.getElementById('progress-bar').style.width =
    ((totalFrame/totalFrames)*100)+'%';
  document.getElementById('scene-label').textContent =
    `Scene ${currentScene+1} / ${SCENES.length}`;
}

function tick(){
  sceneFrame++;
  totalFrame++;
  if(sceneFrame > SCENES[currentScene].duration){
    sceneFrame=0;
    currentScene++;
    if(currentScene >= SCENES.length){
      currentScene = SCENES.length-1;
      sceneFrame = SCENES[currentScene].duration;
      running=false;
      document.getElementById('playBtn').textContent='▶ Play';
      render();
      return;
    }
  }
  render();
  if(running) animId=requestAnimationFrame(tick);
}

function play(){
  running=true;
  document.getElementById('playBtn').textContent='⏸ Pause';
  animId=requestAnimationFrame(tick);
}
function pause(){
  running=false;
  cancelAnimationFrame(animId);
  document.getElementById('playBtn').textContent='▶ Play';
}
function restart(){
  pause();
  currentScene=0; sceneFrame=0; totalFrame=0;
  particles=[];
  render();
}

document.getElementById('playBtn').addEventListener('click',()=>{
  if(running) pause(); else play();
});
document.getElementById('restartBtn').addEventListener('click',()=>{
  restart();
});

// initial frame
render();
</script>
</body>
</html>
Running Command

ls -lh /home/daytona/workspace/drug-abuse-animation/

Your animated drug abuse awareness video is ready! Download and open it in any browser:

index

HTML File · HTML


What's inside the animation

The video has 8 fully animated scenes telling a complete story:
SceneTitleWhat happens
1Title ScreenGlowing title with floating pills, intro text
2Happy LifeAlex the stick-figure student walks to school on a sunny day
3Peer PressureA friend offers a drug at night - "Just try it once!"
4Brain EffectAnimated brain with dopamine surge, explains addiction mechanism
5Downward SpiralRain, broken report card, lost friends, pills on the ground
6Health ConsequencesSplit screen - erratic heartbeat + 5 health effects listed
7Help & RecoveryDoctor + recovering Alex, sunrise, rehab sign
8Say NOBold "SAY NO" with confetti celebration, SAMHSA helpline

How to play it

  • Click ▶ Play to start the animation
  • Click ⏸ Pause to stop at any scene
  • Click ↺ Restart to go back to the beginning
  • A progress bar shows how far along you are
This is a shared conversation. Sign in to Orris to start your own chat.