点击查看html编辑器说明文档

Matter.js 物理引擎弹球动画edit icon

|
|
Fork(复制)
|
|
作者:
穿越者X57

👉 新版编辑器已上线,点击进行体验吧!

BUG反馈
嵌入
设置
下载
HTML
格式化
支持Emmet,输入 p 后按 Tab键试试吧!
<head> <script src="https://cdn...
展开
</head>
<body>
            
            
<div class="shapes"></div>
        
</body>
CSS
格式化
            
            .shapes {
  width:100vw;
  height: 100vh;
}

body {
  background: #e572b0;
  margin: 0;
}
        
JS
格式化
            
            // 从Matter.js引入需要的模块
const { Engine, Events, Body, Render, Bodies, World, MouseConstraint, Composites, Query, Common, Mouse } = Matter

// 获取DOM容器元素
var sectionTag = document.querySelector(".shapes");

// 设置画布宽高
let w = sectionTag.offsetWidth;
let h = sectionTag.offsetHeight;

// 创建物理引擎实例
const engine = Engine.create();

// 设置重力参数
engine.world.gravity.x = 0     // X轴重力为0
engine.world.gravity.y = 0.001 // Y轴微弱重力
engine.world.gravity.scale = 0.1 // 重力比例缩小

// 创建渲染器
var renderer = Render.create({
  element: sectionTag,
  engine: engine,
  options: {
    width: w,
    height: h,
    background: "transparent", // 透明背景
    wireframes: false,        // 关闭线框模式
    pixelRatio: window.devicePixelRatio // 适配设备像素比
  }
});

// 设置墙壁属性
const wallOptions = {
  isStatic: true,           // 静态物体
  render: {
    visible: true,
    fillStyle: "#e572b0",   // 墙壁颜色
  },
  friction: 0,              // 无摩擦力
  restitution: 1.1,         // 弹性系数(大于1表示会增加能量)
}

// 创建四面墙壁
const ceiling = Bodies.rectangle(w / 2, -1, w, 50, wallOptions)      // 天花板
const ground = Bodies.rectangle(w / 2, h+50, w, 50, wallOptions)     // 地面
const leftWall = Bodies.rectangle(-50, h / 2, 50, h, wallOptions)    // 左墙
const rightWall = Bodies.rectangle(w+50, h / 2, 50, h, wallOptions)  // 右墙

// 添加鼠标控制
const mouseControl = MouseConstraint.create(engine, {
  element: sectionTag,
  constraint: {
    render: {
      visible: false  // 隐藏鼠标约束显示
    }
  }
})

// 将墙壁和鼠标控制添加到世界
World.add(engine.world, [
  ground,
  ceiling,
  leftWall,
  rightWall,
  mouseControl,
]);

// 设置小球颜色
var color = "#9bc459";

// 计算小球数量
var peasize = 1225; // 35*35,给最大小球留出空间
var width = window.innerWidth;
var height = window.innerHeight;
var area = width * height;
var areatocover = area * 0.85;  // 覆盖85%的屏幕面积
var numberofpeas = areatocover / peasize;

// 在随机位置添加小球
for (let i = 0; i < numberofpeas; i++) {
  var radius = gsap.utils.random(10, 25);        // 随机半径
  var radius2 = (radius * 2.5);
  var posx = gsap.utils.random(radius2, w - radius2, radius2, true);  // 随机X坐标
  var posy = gsap.utils.random(radius2, h - radius2, radius2, true);  // 随机Y坐标
  
  var scaleFactor = radius * -0.013;  // 计算图片缩放比例

  // 创建圆形物体
  World.add(engine.world, Bodies.circle(
    posx(),
    posy(),
    radius, 
    {
      frictionAir: 0,         // 空气阻力为0
      frictionStatic: 0,      // 静摩擦力为0
      friction: 0,            // 动摩擦力为0
      restitution: 1.01,      // 弹性系数略大于1
      mass: 1,                // 质量为1
      slop: 0,                // 无重叠容差
      render: {
        fillStyle: color,
        sprite: {
          texture: "https://assets.codepen.io/588944/pea3.svg",  // 小球贴图
          xScale: scaleFactor,
          yScale: scaleFactor
        }
      }
    }
  ))
}

// 运行物理引擎和渲染器
Matter.Runner.run(engine);
Matter.Render.run(renderer);

// 监听窗口调整大小事件
window.addEventListener('resize', () => {
  // 更新渲染器尺寸
  renderer.bounds.max.x = sectionTag.clientWidth;
  renderer.bounds.max.y = sectionTag.clientHeight;
  renderer.options.width = sectionTag.clientWidth;
  renderer.options.height = sectionTag.clientHeight;
  renderer.canvas.width = sectionTag.clientWidth;
  renderer.canvas.height = sectionTag.clientHeight;
  Matter.Render.setPixelRatio(renderer, window.devicePixelRatio);

  // 更新地面和右墙的位置
  Matter.Body.setPosition(
    ground,
    Matter.Vector.create(
      sectionTag.clientWidth / 2,
      sectionTag.clientHeight + 50 / 2
    )
  );
  Matter.Body.setPosition(
    rightWall,
    Matter.Vector.create(
      sectionTag.clientWidth + 50 / 2,
      sectionTag.clientHeight / 2
    )
  );
});
        
预览
控制台