All Projects → lixinliang → bubble-hearts

lixinliang / bubble-hearts

Licence: MIT license
(<3kb) 💖Bubble hearts animation.(Canvas 实现直播间点赞动画)

Programming Languages

javascript
184084 projects - #8 most used programming language
HTML
75241 projects

Projects that are alternatives of or similar to bubble-hearts

myaas
Fresh Mysql instances for your developers in seconds
Stars: ✭ 26 (-40.91%)
Mutual labels:  live
raspiCam
RaspiCam, a simple web application to stream, take pictures or record videos from your raspberry pi camera.
Stars: ✭ 43 (-2.27%)
Mutual labels:  live
RtmpPublishKit
rtmp publish kit for android , encode with mediacodec
Stars: ✭ 106 (+140.91%)
Mutual labels:  live
imogen
ultimate vocal harmonizer
Stars: ✭ 169 (+284.09%)
Mutual labels:  live
MMM-NFL
National Football League Module for MagicMirror²
Stars: ✭ 22 (-50%)
Mutual labels:  live
Bilibili Live Barrage
🌈Bilibili_Live_Barrage实时监控B站直播弹幕并发送跟随弹幕
Stars: ✭ 28 (-36.36%)
Mutual labels:  live
htmlhost
hostHTML.live is downright the fastest way of hosting your single page HTML!
Stars: ✭ 21 (-52.27%)
Mutual labels:  live
liveGestureDemo
仿映客双屏直播,OpenCV 竖屏检测,人脸贴纸
Stars: ✭ 26 (-40.91%)
Mutual labels:  live
mock-hls-server
Fake a live/event HLS stream from a VOD one. Useful for testing. Supports looping.
Stars: ✭ 61 (+38.64%)
Mutual labels:  live
multi-live-usb-configs
Syslinux menu scripts to put mulitple livecd distributions on a single USB device.
Stars: ✭ 23 (-47.73%)
Mutual labels:  live
LaravelForLive
视频直播(Laravel)
Stars: ✭ 19 (-56.82%)
Mutual labels:  live
universal-hot-reload
Hot reload client and server webpack bundles for the ultimate development experience
Stars: ✭ 79 (+79.55%)
Mutual labels:  live
digital-canada-ca
Website for the Canadian Digital Service / Site Web du Service numérique canadien
Stars: ✭ 48 (+9.09%)
Mutual labels:  live
inke trick
No description or website provided.
Stars: ✭ 40 (-9.09%)
Mutual labels:  live
ebu-tt-live-toolkit
Toolkit for supporting the EBU-TT Live specification
Stars: ✭ 23 (-47.73%)
Mutual labels:  live
Laravel-rating
Laravel package that allows you to rate, like & dislike and vote(+1,-1) your models with a simple and clear ways
Stars: ✭ 204 (+363.64%)
Mutual labels:  like
obplayer
📻 OBPlayer Streaming Automation Playout with CAP EAS Alerting
Stars: ✭ 93 (+111.36%)
Mutual labels:  live
SFMediaStream
HTML5 media streamer library for playing music, video, playlist, or even live streaming microphone & camera with node server
Stars: ✭ 97 (+120.45%)
Mutual labels:  live
bigscreen-player
Simplified media playback for bigscreen devices
Stars: ✭ 62 (+40.91%)
Mutual labels:  live
acfundanmu
AcFun直播API
Stars: ✭ 27 (-38.64%)
Mutual labels:  live

npm npm npm Twitter

bubble-hearts

(<3kb) 💖Bubble hearts animation.(Canvas 实现直播间点赞动画)

What's it?

  • Let images bubble in canvas, like hearts (etc).
  • It's a familiar animation in live room.
  • Live Demo

bubble-hearts

Getting started

$ npm install --save-dev bubble-hearts

Usage

#Init

let stage = new BubbleHearts();

#Config

let canvas = stage.canvas;
let context = stage.context;
canvas.width = 200;
canvas.height = 400;
canvas.style['width'] = '200px';
canvas.style['height'] = '400px';

#Display

document.body.appendChild(canvas);

#Animate

let image = new Image;
image.onload = () => {
    stage.bubble(image);
};
image.src = src;

Doc

#bubble

stage.bubble( image : Image/Canvas, duration : Number, handler : Function )

Param Type Required Default Description
image Image/Canvas * - Let this image bubbles in canvas.
duration Number - 3000 The duration of animation.
handler Function - @see handler The handler of animation.

#handler

handler( lifespan : Number )

Param Type Description
lifespan Number From 1 to 0; 1 means full live; 0 means over.
  • default handler
/**
 * Create a default Render
 * @param  {Canvas} canvas canvas
 * @param  {Context} context context
 * @return {Function} handler
 */
function createRender ( image, canvas, context ) {

    const zoomInStage = random.uniformDiscrete(89, 91) / 100;
    const zoomInRest = 1 - zoomInStage;
    const basicScale = (random.uniformDiscrete(45, 60) + random.uniformDiscrete(45, 60)) / 100;
    let getScale = ( lifespan ) => {
        if (lifespan > zoomInStage) {
            return Math.max(((1 - lifespan) / zoomInRest).toFixed(2), 0.1) * basicScale;
        } else {
            return basicScale;
        }
    };

    const basicRotate = random.uniformDiscrete(-30, 30);
    let getRotate = ( lifespan ) => {
        return basicRotate;
    };

    const offset = 10;
    const basicTranslateX = canvas.width / 2 + random.uniformDiscrete(-offset, offset);
    const amplitude = (canvas.width - Math.sqrt(Math.pow(image.width, 2) + Math.pow(image.height, 2))) / 2 - offset;
    const wave = random.uniformDiscrete(amplitude * 0.8, amplitude) * (random.uniformDiscrete(0, 1) ? 1 : -1);
    const frequency = random.uniformDiscrete(250, 400);
    let getTranslateX = ( lifespan ) => {
        if (lifespan > zoomInStage) {
            return basicTranslateX;
        } else {
            return basicTranslateX + wave * Math.sin(frequency * (zoomInStage - lifespan) * Math.PI / 180);
        }
    };

    let getTranslateY = ( lifespan ) => {
        return image.height / 2 + (canvas.height - image.height / 2) * lifespan;
    };

    const fadeOutStage = random.uniformDiscrete(14, 18) / 100;
    let getAlpha = ( lifespan ) => {
        if (lifespan > fadeOutStage) {
            return 1;
        } else {
            return 1 - ((fadeOutStage - lifespan) / fadeOutStage).toFixed(2);
        }
    };

    return ( lifespan ) => {
        if (lifespan >= 0) {
            let scale = getScale(lifespan);
            let rotate = getRotate(lifespan);
            let translateX = getTranslateX(lifespan);
            let translateY = getTranslateY(lifespan);
            context.translate(translateX, translateY);
            context.scale(scale, scale);
            context.rotate(rotate * Math.PI / 180);
            context.globalAlpha = getAlpha(lifespan);
            context.drawImage(
                image,
                -image.width / 2,
                -image.height / 2,
                image.width,
                image.height
            );
            context.rotate(-rotate * Math.PI / 180);
            context.scale(1 / scale, 1 / scale);
            context.translate(-translateX, -translateY);
            context.globalAlpha = 1;
        } else {
            return true;
        }
    };
}
  • simple custom example
stage.bubble(image, 3000, function ( lifespan ) {
    // You got its lifespan, and from 1 to 0
    if (lifespan >= 0) {
        stage.context.drawImage(
            image,
            (canvas.width - image.width) / 2,
            // lifespan control its positionY, so that it will look like fly up
            (canvas.height - image.height) * lifespan,
            image.width,
            image.height
        );
    } else {
        // Return true to free the memory
        return true;
    }
});

#why return true ?

  • lifespan from 1 to 0, and go on to be negative.
  • handler function repeats again and again to drawImage.
  • return true is a flag to tell iterator to remove this handler, and stop repeating this handler again.

License

MIT

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].