Canvas实现3D效果

3D 球

效果图

代码

var canvas = document.getElementById("cas"),
    ctx = canvas.getContext("2d"),
    vpx = canvas.width / 2,
    vpy = canvas.height / 2,
    Radius = 150,
    balls = [],
    angleX = Math.PI / 1000,
    angleY = Math.PI / 1000,

    factor = 0.0001 //旋转因子


var Animation = function () {
    this.init();
};
Animation.prototype = {
    init: function () {
        balls = [];
        var num = 500;
        for (var i = 0; i <= num; i++) {
            var k = -1 + (2 * (i + 1) - 1) / num;
            var a = Math.acos(k);
            var b = a * Math.sqrt(num * Math.PI);
            var x = Radius * Math.sin(a) * Math.cos(b);
            var y = Radius * Math.sin(a) * Math.sin(b);
            var z = Radius * Math.cos(a);
            var b = new ball(x, y, z, 1.5);
            balls.push(b);
            b.paint();
        }
    }
}

function animate() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    rotateX();
    rotateY();
    balls.sort(function (a, b) {
        return b.z - a.z;
    })
    for (var i = 0; i < balls.length; i++) {
        balls[i].paint();
    }
}

function rotateX() {
    var cos = Math.cos(angleX);
    var sin = Math.sin(angleX);
    for (var i = 0; i < balls.length; i++) {
        var y1 = balls[i].y * cos - balls[i].z * sin;
        var z1 = balls[i].z * cos + balls[i].y * sin;
        balls[i].y = y1;
        balls[i].z = z1;
    }
}

function rotateY() {
    var cos = Math.cos(angleY);
    var sin = Math.sin(angleY);
    for (var i = 0; i < balls.length; i++) {
        var x1 = balls[i].x * cos - balls[i].z * sin;
        var z1 = balls[i].z * cos + balls[i].x * sin;
        balls[i].x = x1;
        balls[i].z = z1;
    }
}

var ball = function (x, y, z, r) {
    this.x = x;
    this.y = y;
    this.z = z;
    this.r = r;
    this.width = 2 * r;
}

ball.prototype = {
    paint: function () {
        var fl = 450 //焦距
        ctx.save();
        ctx.beginPath();
        var scale = fl / (fl - this.z);
        var alpha = (this.z + Radius) / (2 * Radius);
        ctx.arc(vpx + this.x, vpy + this.y, this.r * scale, 0, 2 * Math.PI, true);
        ctx.fillStyle = "rgba(0,0,0," + (alpha + 0.5) + ")"
        ctx.fill();
        ctx.restore();
    }
}

var animation = new Animation();
canvas.addEventListener('mousedown', onMousedown)

function onMousedown() {
    window.addEventListener('mousemove', onMousemove)
    window.addEventListener('mouseup', onMouseup)
}

function onMousemove(e) {
    var x = e.clientX - canvas.offsetLeft - vpx - document.body.scrollLeft - document.documentElement
        .scrollLeft;
    var y = e.clientY - canvas.offsetTop - vpy - document.body.scrollTop - document.documentElement
        .scrollTop;
    angleY = -x * factor;
    angleX = -y * factor;
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    rotateX();
    rotateY();
    balls.sort(function (a, b) {
        return b.z - a.z;
    })
    for (var i = 0; i < balls.length; i++) {
        balls[i].paint();
    }
}

function onMouseup() {
    window.removeEventListener('mousemove', onMousemove)
    window.removeEventListener('mouseup', onMouseup)
}

参考链接

https://tool.4xseo.com/a/2285.html

相关推荐
Dread_lxy12 分钟前
vue 依赖注入(Provide、Inject )和混入(mixins)
前端·javascript·vue.js
娅娅梨17 分钟前
C++ 错题本--not found for architecture x86_64 问题
开发语言·c++
汤米粥23 分钟前
小皮PHP连接数据库提示could not find driver
开发语言·php
冰淇淋烤布蕾26 分钟前
EasyExcel使用
java·开发语言·excel
拾荒的小海螺32 分钟前
JAVA:探索 EasyExcel 的技术指南
java·开发语言
马剑威(威哥爱编程)1 小时前
哇喔!20种单例模式的实现与变异总结
java·开发语言·单例模式
白-胖-子1 小时前
【蓝桥等考C++真题】蓝桥杯等级考试C++组第13级L13真题原题(含答案)-统计数字
开发语言·c++·算法·蓝桥杯·等考·13级
奔跑草-1 小时前
【前端】深入浅出 - TypeScript 的详细讲解
前端·javascript·react.js·typescript
好睡凯1 小时前
c++写一个死锁并且自己解锁
开发语言·c++·算法
java—大象1 小时前
基于java+springboot+layui的流浪动物交流信息平台设计实现
java·开发语言·spring boot·layui·课程设计