程序员教你用代码制作3d爱心跳动特效,正好拿去送给女神给她个惊喜

简介: 使用HTML、CSS和JavaScript实现了一个三维网格采样器`MeshSurfaceSampler`,适用于任意浏览器,推荐谷歌。代码创建了一个类,从缓冲几何体的三角形网格中进行随机采样。提供了设置权重属性、构建分布和自定义随机数生成器的功能。用户只需将代码复制到文本文档并保存为HTML文件,即可运行。适合编程爱好者尝试,也可分享给他人。

HTML+CSS+JavaScript实现

先点赞后观看,养成好习惯

效果图

注:任意浏览器都可以,建议使用谷歌浏览器

代码部分

代码如下仅供参考
可以直接拿去复制粘贴

(function () {
const _face = new THREE.Triangle();

const _color = new THREE.Vector3();

class MeshSurfaceSampler {

constructor(mesh) {

  let geometry = mesh.geometry;

  if (!geometry.isBufferGeometry || geometry.attributes.position.itemSize !== 3) {

    throw new Error('THREE.MeshSurfaceSampler: Requires BufferGeometry triangle mesh.');

  }

  if (geometry.index) {

    console.warn('THREE.MeshSurfaceSampler: Converting geometry to non-indexed BufferGeometry.');
    geometry = geometry.toNonIndexed();

  }

  this.geometry = geometry;
  this.randomFunction = Math.random;
  this.positionAttribute = this.geometry.getAttribute('position');
  this.colorAttribute = this.geometry.getAttribute('color');
  this.weightAttribute = null;
  this.distribution = null;

}

setWeightAttribute(name) {

  this.weightAttribute = name ? this.geometry.getAttribute(name) : null;
  return this;

}

build() {

  const positionAttribute = this.positionAttribute;
  const weightAttribute = this.weightAttribute;
  const faceWeights = new Float32Array(positionAttribute.count / 3); // Accumulate weights for each mesh face.

  for (let i = 0; i < positionAttribute.count; i += 3) {

    let faceWeight = 1;

    if (weightAttribute) {

      faceWeight = weightAttribute.getX(i) + weightAttribute.getX(i + 1) + weightAttribute.getX(i + 2);

    }

    _face.a.fromBufferAttribute(positionAttribute, i);

    _face.b.fromBufferAttribute(positionAttribute, i + 1);

    _face.c.fromBufferAttribute(positionAttribute, i + 2);

    faceWeight *= _face.getArea();
    faceWeights[i / 3] = faceWeight;

  } // Store cumulative total face weights in an array, where weight index
  // corresponds to face index.


  this.distribution = new Float32Array(positionAttribute.count / 3);
  let cumulativeTotal = 0;

  for (let i = 0; i < faceWeights.length; i++) {

    cumulativeTotal += faceWeights[i];
    this.distribution[i] = cumulativeTotal;

  }

  return this;

}

setRandomGenerator(randomFunction) {

  this.randomFunction = randomFunction;
  return this;

}

sample(targetPosition, targetNormal, targetColor) {

  const cumulativeTotal = this.distribution[this.distribution.length - 1];
  const faceIndex = this.binarySearch(this.randomFunction() * cumulativeTotal);
  return this.sampleFace(faceIndex, targetPosition, targetNormal, targetColor);

}

binarySearch(x) {

  const dist = this.distribution;
  let start = 0;
  let end = dist.length - 1;
  let index = - 1;

  while (start <= end) {

    const mid = Math.ceil((start + end) / 2);

    if (mid === 0 || dist[mid - 1] <= x && dist[mid] > x) {

      index = mid;
      break;

    } else if (x < dist[mid]) {

      end = mid - 1;

    } else {

      start = mid + 1;

    }

  }

  return index;

}

sampleFace(faceIndex, targetPosition, targetNormal, targetColor) {

  let u = this.randomFunction();
  let v = this.randomFunction();

  if (u + v > 1) {

    u = 1 - u;
    v = 1 - v;

  }

  _face.a.fromBufferAttribute(this.positionAttribute, faceIndex * 3);

  _face.b.fromBufferAttribute(this.positionAttribute, faceIndex * 3 + 1);

  _face.c.fromBufferAttribute(this.positionAttribute, faceIndex * 3 + 2);

  targetPosition.set(0, 0, 0).addScaledVector(_face.a, u).addScaledVector(_face.b, v).addScaledVector(_face.c, 1 - (u + v));

  if (targetNormal !== undefined) {

    _face.getNormal(targetNormal);

  }

  if (targetColor !== undefined && this.colorAttribute !== undefined) {

    _face.a.fromBufferAttribute(this.colorAttribute, faceIndex * 3);

    _face.b.fromBufferAttribute(this.colorAttribute, faceIndex * 3 + 1);

    _face.c.fromBufferAttribute(this.colorAttribute, faceIndex * 3 + 2);

    _color.set(0, 0, 0).addScaledVector(_face.a, u).addScaledVector(_face.b, v).addScaledVector(_face.c, 1 - (u + v));

    targetColor.r = _color.x;
    targetColor.g = _color.y;
    targetColor.b = _color.z;
  }
  return this;

}

}

THREE.MeshSurfaceSampler = MeshSurfaceSampler;

})();

运行步骤,在桌面新建个文本文档,将代码全部复制到文档后保存,然后重命名将.txt文件修改成.html文件最后点击文件就能运行成功啦,运行成功了快快发给爱慕女孩,说不定就能收获到爱情啦。(如果有不想动手的小伙伴可以私聊博主获取哦!!!!)

相关文章
|
5天前
|
前端开发 JavaScript 程序员
程序员教你用代码制作圣诞树,正好圣诞节拿去送给女神给她个惊喜
使用HTML、CSS和JavaScript实现了一个圣诞树效果,包括一个闪烁的圣诞树和一个动态的光斑。代码包含一个&lt;div&gt;元素作为遮罩,一个&lt;canvas&gt;元素绘制星星动画,以及一个SVG元素绘制圣诞树。页面还包含一个提示用户先点赞再观看的提示。此效果适用于任何浏览器,推荐使用谷歌浏览器。提供了一段HTML代码,可以直接复制粘贴到文件中并以.html格式打开查看效果。
|
5天前
|
Java
普通玩家也能掌握的Java游戏加点系统,专业到让你无敌!
普通玩家也能掌握的Java游戏加点系统,专业到让你无敌!
15 1
|
9月前
四、巧用Camtasia来剪视频 | 微课系列教程
因为平时我们要用到的视频操作很多,视频拼接、细节修正、从长视频中取一部分等等。那么本课以微课录制后的视频裁剪为例,教大家一些简单的视频剪切和音频杂音处理,最后导出视频。
75 0
|
10月前
【代码分享】【像极了恋爱】甜甜的汤圆,祝丽姿元宵快乐(表白特效)
【代码分享】【像极了恋爱】甜甜的汤圆,祝丽姿元宵快乐(表白特效)
|
11月前
|
C语言
无敌!我用【C语言】手搓出了一个体系完整的【员工管理系统】还能玩游戏听音乐?(超详细,附完整源码)
前言:员工管理系统是一款面向公司管理员的管理工具,旨在提供员工信息管理、薪资管理、员工绩效评估、员工福利管理和智能推荐等功能,帮助公司管理员更好地管理员工信息和提高员工工作效率。 这是总体设计大概模型图:
112 0
|
12月前
游戏开发零基础入门教程(5):不要挡住我,我要去上面
这一节我们学习了层级管理,以及通过使用拖拽的方式来调整层级的顺序。 在真实的游戏中可能会包含很多的层级,在调整层级时,不要忘记口诀:谁挡住了我,我就去谁的上面。 试着在游戏中加入更多的层级,拖拽调整层级的顺序,然后观察编辑区中的图片显示效果。
129 0
|
数据挖掘 开发者
关于泡泡龙游戏的一点儿总结,以及分享一个好方法
游戏是一种虚拟的产品,它很难被量化,也很难像工厂流水线生产实体产品一样的去生产。因为其中涉及到的情况太多太杂,如何衡量一个游戏的体量?怎样的游戏算是大游戏,怎样的游戏算是小游戏呢?如何判断一个游戏是做完了还是没有做完呢?如何衡量一个游戏开发者的水平呢?……等等等等。这里面的每一个因素都是一个变量,这么多的无法确定的变量合在一起,想要得到一个确定的结果,很显然是不太可能的。
109 0
|
前端开发 容器
浮动流这操作秀了小白我一脸
问题是这样的,需要将 box 宽度为 580px 的盒子中放 5 个小的 item,item的宽度为 100px
67 0
浮动流这操作秀了小白我一脸
|
前端开发 JavaScript
2023跨年烟花(浪漫烟花+美妙音乐+雪花飘飘)含前端源码直接下载---系列最终篇
2023跨年烟花(浪漫烟花+美妙音乐+雪花飘飘)含前端源码直接下载---系列最终篇
421 0
2023跨年烟花(浪漫烟花+美妙音乐+雪花飘飘)含前端源码直接下载---系列最终篇
|
前端开发 JavaScript 程序员
2023将至,前端程序员们应该一起放个烟花庆祝一下,走起
前言:小时候,在我印象中,每到快过年的时候就有很多卖炮仗的,一般也就是阳历的12月份到明年的正月15号卖炮仗的商家比较多,省下买辣条的钱去买炮仗,在老家也就过年和除夕两天及正月15日这几天放烟花和炮仗比较猛,现在年纪大了,听不得炮仗那种噪声了,也考虑到环保,工作之后的程序员以代码的形式演绎一下烟花的效果。
227 0
2023将至,前端程序员们应该一起放个烟花庆祝一下,走起