npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@simon_he/s-three

v0.0.17

Published

s-three

Downloads

155

Readme

sThree

  • 简单化three的使用
  • 可以让你的代码更加简洁,更加美观
  • 不需要在onMounted中执行,可以在任意时刻使用
  • 自动监听resize事件,自动更新canvas的大小
  • 内置了一下简单的创建函数和一些修改属性函数后自动化更新视图的功能比如texture的加载不必额外再调用.load,可以直接传图片地址,并且这个texture是会被cache的,内置了dat.gui的debugger功能,可开启debug:true,在createMesh中结构track函数使用,如果是geometry的color需要addColor和额外设置geometry.color.set,可直接通过track('color',geometry,'color')就会自动去setColor,追加了_add方法会导出一个销毁原mesh的方法,const unmount = scene._add(mesh) ,可在更新前调用unmount方法卸载mesh,更新后调用mount方法重新添加mesh
  • 参数:
    • container: string | HTMLElement, 父容器
    • options: { createMesh: () => void createCamera: (scene: Object3D) => PerspectiveCamera /* 创建camera, const camera = c("PC"); return camera, 返回的camera会被添加到scene中 / animate?: (animationOptions: AnimateOptions) => void | THREE.PerspectiveCamera / 动画函数,每秒60帧,可以在这里添加修改camera或者mesh的属性,会被自动update,如果需要使用新的camera在这里返回一个新的camera即可 / middleware?: (middlewareOptions: MiddlewareOptions) => any / 中间件函数,可以在这里额外做一下操作,比如添加axes,使用 OrbitControls等等,返回的内容会被传入到animation函数中的params中 / mousemove?: (e: Event) => void / 自动监听画布的mousemove事件 / mousedown?: (e: Event) => void / 自动监听画布的mousedown事件 / mouseup?: (e: Event) => void / 自动监听画布的mouseup事件 / debug?: boolean / 是否开启debug模式,默认false / alias?: Record<string, string> / 配置别名,在c函数中作为映射使用例如 {m:"Mesh",pc:"PerspectiveCamera"}等等,根据自己的命名规则来配置别名 */ }
  • 返回值:
    • ReturnType { c: (fnName: keyof FnNameMap | keyof T, ...args: any[]) => any /* 使用c可以更简洁的创建一些geometry、material、texture等,如c("m",c('bg',1,1,1),c('msm'))等同于创建一个Mesh,bg是一个1x1x1的boxGeometry,msm是一个MeshStandardMaterial / cf: (url: string, text: string, options: TextGeometryParameters) => Promise / 创建文字geometry,可以传入文字内容和文字配置参数,返回Promise track: (...args: [target: Object, propName: string, min?: number, max?: number, step?: number]) => dat.GUIController // 开启右上角的debugger,可以追踪mesh的属性,可以在这里添加修改mesh的属性,会被自动update,如track('color',mesh,'color')就会自动去setColor,追加了_add方法会导出一个销毁原mesh的方法,const unmount = scene._add(mesh) ,可在更新前调用unmount方法卸载mesh,更新后调用mount方法重新添加mesh / setUV: (target: Mesh, size?: number) => void // 快速设置geometry的uv,可以传入size参数,默认为2 glTFLoader: (url: string, dracoLoader?: DRACOLoader, callback?: (gltf: GLTFLoader) => void) => Promise / 创建gltf加载器,可以传入dracoLoader参数,如果需要使用draco加载器,需要引入draco-loader,并且在callback中设置dracoLoader参数,返回Promise,可直接获取load后的结果,如const gltf = await glTFLoader('/model.gltf') ,gltf.scene就是gltf的scene对象,并且gltf是能够被cache使用同一个gltfLoader / draCOLoader: (decoderPath: string) => DRACOLoader / 创建draco加载器,可以传入decoderPath参数,返回DRACOLoader / animationArray: Mesh[] / 动画数组,用于记录所有的动画mesh,可在animation函数中去批量更新mesh的属性,如animationArray.forEach(mesh => mesh.rotation.x += 0.01) / THREE: T / THREE对象 / scene: Scene / 场景对象 / renderer: WebGLRenderer / 渲染器对象 / dom: HTMLCanvasElement / dom实例 / setRendererAttributes: (options: Record<K, any>) => void / 批量添加renderer的属性,可以在这里添加修改renderer的属性,会被自动update,如setRendererAttributes({antialias:true})就会自动设置antialias为true */ }
const {
  c,
  track,
  cf,
  animationArray,
  glTFLoader,
  draCOLoader,
  setUV,
  THREE,
  scene,
  dom,
  renderer,
} = sThree('#galaxy', {
  createMesh() {
    // Galaxy
    const params = {
      count: 30000,
      size: 0.02,
      radius: 4.5,
      branch: 8,
      spin: 1,
      randomness: 0.35,
      randomnessPower: 3,
      insideColor: '#b77863',
      outsideColor: '#2755e2',
    }
    let geometry
    let material
    let points
    let unmount
    const generateGalaxy = () => {
      if (points)
        unmount()
      geometry = c('bufferg')
      const positions = new Float32Array(params.count * 3)
      const colors = new Float32Array(params.count * 3)
      const colorInside = new THREE.Color(params.insideColor)
      const colorOutside = new THREE.Color(params.outsideColor)
      for (let i = 0; i < params.count; i++) {
        const i3 = i * 3
        // Position
        const radius = Math.random() * params.radius
        const spinAngle = radius * params.spin
        const randomX
          = Math.random() ** params.randomnessPower
            * (Math.random() < 0.5 ? -1 : 1)
            * params.randomness
        const randomY
          = Math.random() ** params.randomnessPower
            * (Math.random() < 0.5 ? -1 : 1)
            * params.randomness
        const randomZ
          = Math.random() ** params.randomnessPower
            * (Math.random() < 0.5 ? -1 : 1)
            * params.randomness
        const branchAngle = ((i % params.branch) / params.branch) * Math.PI * 2 + randomX
        positions[i3 + 0] = Math.cos(branchAngle + spinAngle) * radius
        positions[i3 + 1] = 0 + randomY
        positions[i3 + 2] = Math.sin(branchAngle + spinAngle) * radius + randomZ
        // Color
        const mixedColor = colorInside.clone()
        mixedColor.lerp(colorOutside, radius / params.radius)
        colors[i3 + 0] = mixedColor.r
        colors[i3 + 1] = mixedColor.g
        colors[i3 + 2] = mixedColor.b
      }
      geometry.setAttribute('position', c('ba', positions, 3))
      geometry.setAttribute('color', c('ba', colors, 3))
      console.log(geometry)
      // Material
      material = c('pm', {
        size: params.size,
        sizeAttenuation: true,
        depthWrite: false,
        blending: THREE.AdditiveBlending,
        vertexColors: true,
      })
      points = c('p', geometry, material)
      unmount = scene._add(points)
      animationArray.push(points)
    }
    track(params, 'count').min(100).max(100000).step(100).onFinishChange(generateGalaxy)
    track(params, 'size').min(0.001).max(0.1).step(0.001).onFinishChange(generateGalaxy)

    track(params, 'radius').min(0.01).max(20).step(0.01).onFinishChange(generateGalaxy)
    track(params, 'branch').min(2).max(20).step(1).onFinishChange(generateGalaxy)
    track(params, 'spin').min(-5).max(5).step(0.001).onFinishChange(generateGalaxy)
    track(params, 'randomness').min(0).max(2).step(0.001).onFinishChange(generateGalaxy)
    track(params, 'randomnessPower')
      .min(1)
      .max(10)
      .step(0.001)
      .onFinishChange(generateGalaxy)
    track('color', params, 'insideColor').onFinishChange(generateGalaxy)
    track('color', params, 'outsideColor').onFinishChange(generateGalaxy)
    generateGalaxy()
  },
  createCamera(scene) {
    const camera = c('PC')
    camera.position.z = 1
    camera.position.y = 4
    return camera
  },
  middleware({ camera, OrbitControls }) {
    const controls = new OrbitControls(camera, dom)
  },
  animate({ camera, elapsedTime, params }) {
    animationArray[0].rotation.y = elapsedTime * 0.1
  },
  debug: true,
})