mirror of
https://github.com/direct-img/vibegif.direct-img.link.git
synced 2026-10-29 19:54:51 +00:00
Anime, 50 more colored girls: daily moments (yawn, hiccup, toothbrush, hair dryer, blanket burrito, pocky), hobbies (baker, barista, DJ, piano, violin, polaroid, knitting, origami, pottery), sports (swimming, tennis, badminton, skating, ballet, jump rope, hula hoop, bicycle, campfire, surfing), holidays (halloween, christmas, valentine, mochi, birthday, easter, tsukimi, suikawari, taiko, teru teru bozu) and fantasy (fairy, bunny hood, slime, cyber, magical girl, alien, jiangshi, tanuki, yuki-onna, little devil). Manga, 50 more black-and-white girls: reactions (doki, stare, ufufu, denial, fired up, panic, sigh, confused, shiver, poka poka), sports and martial arts (boxing, fencing, volleyball, sprint, gymnast, baseball, naginata, nunchaku, parkour, motorbike), school (library, flute, calligraphy, science, hanko, transfer student, tug of war, sweeping, note passing, yakisoba bread), home and town (claw machine, cooking, ironing, bus stop, matcha, sewing, boxes, stray cat, foggy window, piggy bank) and yokai and fantasy (tengu, kappa, rokurokubi, temari, alchemist, mummy, wolf girl, medusa, genie, bard). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
60 lines
5.8 KiB
JavaScript
60 lines
5.8 KiB
JavaScript
// side-view chibi transfer student with ink low twin tails bowing deeply by the chalkboard with her name on it, then popping up with a happy sparkle
|
|
import{createCanvas}from'@napi-rs/canvas'
|
|
const{sin,cos,PI,min,max}=Math,T=2*PI
|
|
export const frames=20,delay=80,rim=4
|
|
const tile=createCanvas(6,6),q=tile.getContext('2d');q.fillStyle='#111';for(const[x,y]of[[1.5,1.5],[4.5,4.5]])q.beginPath(),q.arc(x,y,1.1,0,T),q.fill()
|
|
const toned=(c,p)=>{c.fillStyle='#fff';c.fill();c.fillStyle=p;c.fill();c.stroke()}
|
|
const ease=f=>f<=0?0:f>=1?1:.5-.5*cos(PI*f)
|
|
const H=[132,182],C=[136,90]
|
|
const spark=(c,x,y,s)=>{c.beginPath();for(let k=0;k<8;k++){const a=k*PI/4,r=k%2?s*.35:s;c.lineTo(x+r*cos(a),y+r*sin(a))}c.closePath();c.fill();c.stroke()}
|
|
export default(c,t)=>{
|
|
const dot=c.createPattern(tile,'repeat')
|
|
const b=t<.1?0:t<.3?ease((t-.1)/.2):t<.5?1:t<.65?1-ease((t-.5)/.15):0,a=.85*b,shut=t>=.15&&t<.58,happy=t>=.62&&t<.95
|
|
// chalkboard behind with her name, 山田, in chalk
|
|
c.lineWidth=5;c.fillStyle='#fff';c.beginPath();c.rect(8,34,88,94);c.fill();c.stroke()
|
|
c.fillStyle='#111';c.beginPath();c.rect(15,41,74,80);c.fill()
|
|
c.strokeStyle='#fff';c.lineWidth=3.5;c.beginPath();c.moveTo(35,54);c.lineTo(35,78);c.moveTo(24,63);c.lineTo(24,78);c.lineTo(46,78);c.lineTo(46,63);c.rect(57,56,22,22);c.moveTo(68,56);c.lineTo(68,78);c.moveTo(57,67);c.lineTo(79,67);c.stroke()
|
|
c.beginPath();c.moveTo(28,92);c.lineTo(76,92);c.stroke();c.beginPath();c.moveTo(52,104);c.bezierCurveTo(44,96,38,106,52,114);c.bezierCurveTo(66,106,60,96,52,104);c.stroke()
|
|
c.strokeStyle='#111';c.lineWidth=4;c.fillStyle='#fff';c.beginPath();c.rect(10,128,84,8);c.fill();c.stroke()
|
|
// legs and shoes stay planted
|
|
c.lineWidth=4;for(const[x0,x1]of[[124,122],[140,144]]){c.fillStyle='#fff';c.beginPath();c.moveTo(x0-6,196);c.lineTo(x1-6,230);c.lineTo(x1+6,230);c.lineTo(x0+6,196);c.closePath();c.fill();c.stroke()
|
|
c.beginPath();c.moveTo(x1-6,216);c.lineTo(x1+6,216);c.stroke();c.fillStyle='#111';c.beginPath();c.ellipse(x1+5,235,13,7,0,0,T);c.fill()}
|
|
c.fillStyle='#fff';c.lineWidth=3;c.beginPath();c.ellipse(124,232,12,4,0,0,T);c.fill();c.lineWidth=4
|
|
// pleated dotted skirt, tipping a little with the bow
|
|
c.save();c.translate(...H);c.rotate(a*.2);c.translate(-H[0],-H[1])
|
|
c.beginPath();c.moveTo(118,178);c.lineTo(150,178);c.lineTo(162,208);c.lineTo(106,208);c.closePath();toned(c,dot)
|
|
c.lineWidth=2.5;for(const x of[124,134,144])c.beginPath(),c.moveTo(x,180),c.lineTo(x+(x-134)*.4,206),c.stroke()
|
|
c.restore()
|
|
// upper body bows from the hips
|
|
c.save();c.translate(...H);c.rotate(a);c.translate(-H[0],-H[1])
|
|
// twin tails dangle with gravity
|
|
for(const[x,y,o]of[[114,112,-6],[118,116,4]]){c.save();c.translate(x,y);c.rotate(-a*.85+.05*sin(T*2*t+o));c.lineWidth=5;c.fillStyle='#111';c.beginPath();c.moveTo(-6,0);c.quadraticCurveTo(-18+o,30,-8+o*.5,62);c.quadraticCurveTo(0,52,6,0);c.closePath();c.fill();c.stroke()
|
|
c.strokeStyle='#fff';c.lineWidth=2.5;c.beginPath();c.moveTo(-4,10);c.quadraticCurveTo(-10+o,30,-6+o*.5,46);c.stroke();c.strokeStyle='#111'
|
|
c.fillStyle='#fff';c.lineWidth=4;c.beginPath();c.ellipse(0,2,9,6,0,0,T);c.fill();c.stroke();c.restore()}
|
|
// sailor top with the square collar at the back and a ribbon in front
|
|
c.lineWidth=5;c.fillStyle='#fff';c.beginPath();c.roundRect(118,126,32,58,8);c.fill();c.stroke()
|
|
c.lineWidth=4;c.beginPath();c.moveTo(118,128);c.lineTo(138,128);c.lineTo(132,156);c.lineTo(114,152);c.closePath();toned(c,dot)
|
|
c.fillStyle='#111';c.beginPath();c.moveTo(148,138);c.lineTo(160,132);c.lineTo(158,146);c.closePath();c.fill();c.beginPath();c.moveTo(150,140);c.lineTo(156,160);c.lineTo(146,156);c.closePath();c.fill()
|
|
for(const[l,s]of[[16,'#111'],[10,'#fff']])c.lineWidth=l,c.strokeStyle=s,c.beginPath(),c.moveTo(136,136),c.quadraticCurveTo(140,160,152,174),c.stroke()
|
|
c.strokeStyle='#111';c.fillStyle='#fff';c.lineWidth=4;c.beginPath();c.ellipse(154,176,8,7,0,0,T);c.fill();c.stroke()
|
|
c.beginPath();c.rect(130,118,10,10);c.fill()
|
|
// profile head
|
|
c.lineWidth=6;c.beginPath();c.arc(...C,40,0,T);c.fill();c.stroke()
|
|
c.lineWidth=3;c.beginPath();c.moveTo(175,96);c.lineTo(179,101);c.lineTo(175,103);c.stroke()
|
|
c.lineWidth=6;c.fillStyle='#111';c.beginPath();c.arc(C[0],C[1],44,-.1*PI,.65*PI,true);c.lineTo(122,112);c.quadraticCurveTo(122,86,140,74)
|
|
for(const[x,y]of[[146,86],[152,74],[160,90],[166,76],[174,90]])c.lineTo(x,y);c.closePath();c.fill();c.stroke()
|
|
c.strokeStyle='#fff';c.lineWidth=4;c.beginPath();c.arc(C[0],C[1],34,1.15*PI,1.45*PI);c.stroke();c.strokeStyle='#111'
|
|
c.fillStyle='#fff';c.lineWidth=4;c.beginPath();c.ellipse(126,102,7,9,0,0,T);c.fill();c.stroke();c.lineWidth=2;c.beginPath();c.arc(127,102,4,.6*PI,1.5*PI);c.stroke()
|
|
// eye: open, squeezed shut while bowing, or a happy arc
|
|
if(shut){c.lineWidth=4.5;c.beginPath();c.moveTo(153,96);c.lineTo(165,100);c.lineTo(155,105);c.stroke()}
|
|
else if(happy){c.lineWidth=4.5;c.beginPath();c.arc(160,102,7,1.1*PI,1.9*PI);c.stroke()}
|
|
else{c.fillStyle='#fff';c.beginPath();c.ellipse(161,100,7,11,0,0,T);c.fill();c.fillStyle='#111';c.beginPath();c.ellipse(163,101,5,9,0,0,T);c.fill();c.fillStyle='#fff';c.beginPath();c.arc(162,97,2.2,0,T);c.fill()
|
|
c.lineWidth=4.5;c.beginPath();c.moveTo(153,90);c.quadraticCurveTo(162,86,170,91);c.lineTo(174,87);c.stroke()}
|
|
c.lineWidth=2.2;for(let k=0;k<3;k++)c.beginPath(),c.moveTo(150+k*5,114),c.lineTo(154+k*5,108),c.stroke()
|
|
c.lineWidth=3;c.beginPath();if(happy){c.fillStyle='#111';c.moveTo(163,114);c.quadraticCurveTo(170,124,175,113);c.closePath();c.fill()}else c.moveTo(166,116),c.quadraticCurveTo(170,118,173,115);c.stroke()
|
|
// nervous sweat drop while she holds the bow
|
|
if(t>=.3&&t<.52){c.fillStyle='#fff';c.lineWidth=3;c.beginPath();c.moveTo(166,40);c.quadraticCurveTo(176,54,166,58);c.quadraticCurveTo(156,54,166,40);c.fill();c.stroke()}
|
|
c.restore()
|
|
if(happy){c.fillStyle='#fff';c.lineWidth=3;const s=1+.4*sin(T*(t-.62)*6);for(const[x,y,r]of[[186,34,10],[214,66,7],[110,24,8]])spark(c,x,y,r*s)}
|
|
}
|