├── .eslintrc.js ├── .gitignore ├── 3d-basic ├── cube.html └── cylinder.html ├── 3d-camera ├── cylinder-clip.html ├── cylinder-ortho.html ├── cylinder-perspective.html ├── cylinder.html └── ogl-basic.html ├── 3d-model ├── axis-angle.html └── euler-angle.html ├── LICENSE ├── README.md ├── animate ├── animate_delta.html ├── animate_time.html ├── animator.html ├── frame_animate.html ├── lerp-bezier-css.html ├── lerp-bezier.html └── lerp.html ├── animate_webgl ├── bezier_easing.html ├── cellular-animation.html ├── fragment_rotation_animator.html ├── fragment_rotation_animator2.html ├── frame_animate.html ├── lerp.html ├── lerp_easing.html ├── particle.html ├── vertex_move_animator.html ├── vertex_move_easing.html ├── vertex_rotation.html └── vertex_rotation_animator.html ├── assets ├── airplane.jpg ├── airplane.json ├── github_contributions_akira-cn.json ├── normal_map.png ├── normal_plane.jpg ├── rock.jpg ├── rock_normal.jpg └── rounded-cube.json ├── bezier ├── app.js ├── app2.js ├── cubic.html └── quadratic.html ├── canvas ├── basic │ └── index.html ├── hierarchy │ ├── app.js │ └── index.html └── test.html ├── color-hints ├── app-cubehelix.js ├── app-hsl-problem.js ├── app-hsl.js ├── app-lab.js ├── app-rgb.js ├── color-cubehelix.html ├── color-hints-hsl.html ├── color-hints-rgb.html ├── color-hsl-problem.html └── color-lab.html ├── common └── lib │ ├── animator │ ├── index.js │ └── timing.js │ ├── color │ └── cubehelix │ │ ├── index.js │ │ └── matrix.js │ ├── dat.gui.js │ ├── earcut.js │ ├── gl-renderer.js │ ├── math │ ├── Color.js │ ├── Euler.js │ ├── Mat3.js │ ├── Mat4.js │ ├── Quat.js │ ├── README.md │ ├── Vec2.js │ ├── Vec3.js │ ├── Vec4.js │ └── functions │ │ ├── ColorFunc.js │ │ ├── EulerFunc.js │ │ ├── Mat3Func.js │ │ ├── Mat4Func.js │ │ ├── QuatFunc.js │ │ ├── Vec2Func.js │ │ ├── Vec3Func.js │ │ └── Vec4Func.js │ ├── ogl │ ├── core │ │ ├── Camera.js │ │ ├── Geometry.js │ │ ├── Mesh.js │ │ ├── Program.js │ │ ├── RenderTarget.js │ │ ├── Renderer.js │ │ ├── Texture.js │ │ └── Transform.js │ ├── extras │ │ ├── Animation.js │ │ ├── Box.js │ │ ├── Curve.js │ │ ├── Cylinder.js │ │ ├── Flowmap.js │ │ ├── GLTFAnimation.js │ │ ├── GLTFLoader.js │ │ ├── GLTFSkin.js │ │ ├── GPGPU.js │ │ ├── KTXTexture.js │ │ ├── NormalProgram.js │ │ ├── Orbit.js │ │ ├── Plane.js │ │ ├── Polyline.js │ │ ├── Post.js │ │ ├── Raycast.js │ │ ├── Shadow.js │ │ ├── Skin.js │ │ ├── Sphere.js │ │ ├── Text.js │ │ ├── TextureLoader.js │ │ ├── Torus.js │ │ └── Triangle.js │ ├── index.mjs │ └── math │ │ ├── Color.js │ │ ├── Euler.js │ │ ├── Mat3.js │ │ ├── Mat4.js │ │ ├── Quat.js │ │ ├── Vec2.js │ │ ├── Vec3.js │ │ ├── Vec4.js │ │ └── functions │ │ ├── ColorFunc.js │ │ ├── EulerFunc.js │ │ ├── Mat3Func.js │ │ ├── Mat4Func.js │ │ ├── QuatFunc.js │ │ ├── Vec2Func.js │ │ ├── Vec3Func.js │ │ └── Vec4Func.js │ ├── parametric.js │ ├── phong.js │ └── vector2d.js ├── coordinates ├── app.js └── index.html ├── covid-vis ├── assets │ └── data │ │ ├── covid-data-unpressed.json │ │ ├── covid-data.json │ │ ├── t01cd3ca6de977c52a9.jpg │ │ ├── world-geojson.json │ │ ├── world-topojson.json │ │ └── world-uncompressed.json ├── covid-dynamic.html ├── covid-static.html ├── mercator-topojson.html └── mercator.html ├── d3-spritejs ├── bar-graph.html └── force.html ├── d3 ├── d3-dom.html └── d3-spritejs.html ├── data-graph-css ├── areagraph.html ├── bargraph.html ├── linegraph.html └── piegraph.html ├── data-graph-svg └── bargraph.html ├── data ├── park-people │ ├── charts.html │ ├── charts2.html │ ├── charts3.html │ ├── charts4.html │ ├── data.json │ ├── source.html │ └── spritejs.js ├── weather.zip └── weather │ ├── 2013-2018.csv │ ├── beijing_2014.csv │ ├── index1.html │ ├── index2.html │ ├── index3.html │ ├── index4.html │ ├── index5.html │ ├── index6.html │ └── index7.html ├── github-contributions └── index.html ├── gl-raffle ├── index.html └── lib │ ├── fragment.glsl │ ├── gl-renderer.js │ ├── members.js │ └── prizes.js ├── lights ├── ambient-light.html ├── directional-light.html ├── phong.html ├── point-light.html ├── specular.html └── spot-light.html ├── misc ├── path_intersection.html ├── path_intersection_record.html └── video.html ├── noise ├── basic.html ├── cellular-noise.html ├── clouds.html ├── gradient-noise.html ├── noise-lines.html ├── noise-sdf.html ├── noise-sky.html ├── noise2d.html └── simplex-noise.html ├── normal-maps ├── cube.html └── rock.html ├── package.json ├── parametric-polar ├── app.js └── index.html ├── parametric ├── app.js └── index.html ├── parametric2 ├── app.js └── index.html ├── pass ├── bloom.html ├── blur.html └── smoke.html ├── performance-basic ├── canvas-circles.html ├── ogl-circles.html └── svg-circles.html ├── performance-more ├── point-primitives-circle.html ├── point-primitives-rect.html ├── spots-batch.html ├── spots-normal.html └── spots-points-batch.html ├── performance-webgl ├── random-shapes-1.html ├── random-shapes-2.html ├── random-triangles-1.html ├── random-triangles-2.html └── random-triangles-3.html ├── performance_canvas ├── layers.html ├── random_shapes.html ├── random_shapes_cache.html ├── random_shapes_filter.html ├── random_shapes_filter_pass.html ├── random_shapes_optimized.html ├── random_shapes_path2d.html ├── random_shapes_worker.html └── random_shapes_worker.js ├── pixels-shader ├── combine.html ├── particle.html └── texture.html ├── pixels ├── assets │ ├── explode.jpg │ ├── girl1.jpg │ ├── girl2.jpg │ ├── girl3.jpg │ └── sunlight.png ├── index1.html ├── index2-2.html ├── index2-3.html ├── index2.html ├── index3.html ├── index4.html ├── index5.html ├── index6.html ├── index7.html └── lib │ ├── color-matrix.js │ ├── image-data.js │ ├── math.js │ └── util.js ├── polar-shader ├── bud.html ├── circle.html ├── clover.html ├── conic.html ├── hsvwheel.html ├── rose.html └── rose2.html ├── polygon-fill ├── app.js └── fill-canvas2d.html ├── polyline-curve ├── canvas2d.html ├── webgl-lines-extrude.html └── webgl-lines.html ├── qcharts ├── area.html ├── bar.html ├── basic.html ├── gauge.html ├── line-bar.html ├── line.html ├── pie.html ├── radar.html └── radial.html ├── repeat-and-random ├── grids.html ├── mandelbrot.html ├── maze.html ├── random.html └── random2.html ├── shaping-functions ├── basic.html ├── circle-repeat.html ├── circle.html ├── circle_particle.html ├── clip.html ├── line-mouse.html ├── line-repeat.html ├── line.html ├── lineseg-mouse.html ├── progress.html ├── triangle-repeat.html └── triangles.html ├── sketch ├── index1.html ├── index10.html ├── index2.html ├── index3.html ├── index4.html ├── index5.html ├── index6.html ├── index7.html ├── index8.html ├── index9.html └── lib │ └── doodle.js ├── svg ├── basic │ └── index.html └── hierarchy │ ├── app.js │ └── index.html ├── triangluations ├── app-collision.js ├── app.js ├── app2d.js ├── polygon2d-collision.html ├── polygon2d.html └── trianglu-polygon.html ├── vector_draw ├── app.js └── index.html ├── vector_tree ├── app.js └── index.html ├── vis-geo-earth ├── .babelrc ├── .demosrc.js ├── .eslintrc.js ├── README.md ├── demos │ ├── .demoList.json │ ├── basical │ │ ├── config.js │ │ └── index.js │ ├── beams │ │ ├── config.js │ │ └── index.js │ ├── camera │ │ ├── config.js │ │ └── index.js │ ├── curves │ │ ├── config.js │ │ └── index.js │ ├── globe │ │ ├── config.js │ │ └── index.js │ ├── index.html │ ├── markers │ │ ├── config.js │ │ └── index.js │ ├── missiles │ │ ├── config.js │ │ └── index.js │ ├── normalmap │ │ ├── config.js │ │ └── index.js │ └── style.css ├── dist │ ├── sprite-extend-3d.js │ ├── sprite-geo-earth.esm.js │ ├── sprite-geo-earth.js │ ├── sprite-geo-earth.min.js │ └── spritejs.js ├── docs │ ├── assets │ │ ├── css │ │ │ └── chunk-vendors.cbc1d7ee.chunk.css │ │ └── js │ │ │ ├── 0.9783eddd.chunk.js │ │ │ ├── 1.a4a3b37a.chunk.js │ │ │ ├── 10.44fd260e.chunk.js │ │ │ ├── 11.0302456c.chunk.js │ │ │ ├── 12.161e71f1.chunk.js │ │ │ ├── 13.56a12e9d.chunk.js │ │ │ ├── 14.f9d6b8f4.chunk.js │ │ │ ├── 15.19e14411.chunk.js │ │ │ ├── 16.b63b9b8d.chunk.js │ │ │ ├── 17.44c46fa2.chunk.js │ │ │ ├── 18.414032b6.chunk.js │ │ │ ├── 19.5715201d.chunk.js │ │ │ ├── 2.8c8886c1.chunk.js │ │ │ ├── 20.c3830c06.chunk.js │ │ │ ├── 21.0dc47427.chunk.js │ │ │ ├── 22.8aeb7dae.chunk.js │ │ │ ├── 23.086e08e0.chunk.js │ │ │ ├── 24.57abd3d7.chunk.js │ │ │ ├── 25.3dc71cba.chunk.js │ │ │ ├── 26.56fa9a57.chunk.js │ │ │ ├── 27.3e5605d9.chunk.js │ │ │ ├── 28.408703be.chunk.js │ │ │ ├── 29.54152f91.chunk.js │ │ │ ├── 30.b8ac2ad7.chunk.js │ │ │ ├── 31.176633d2.chunk.js │ │ │ ├── 32.f0c049fa.chunk.js │ │ │ ├── 33.c0d60149.chunk.js │ │ │ ├── 34.8fd02ac4.chunk.js │ │ │ ├── 35.6a800636.chunk.js │ │ │ ├── 36.a5b935b2.chunk.js │ │ │ ├── 37.4e6f467b.chunk.js │ │ │ ├── 38.2bc552fb.chunk.js │ │ │ ├── 39.f9c5c8de.chunk.js │ │ │ ├── 40.e3ed0fab.chunk.js │ │ │ ├── 41.f5f51c5b.chunk.js │ │ │ ├── 42.9787e556.chunk.js │ │ │ ├── 43.57c1cef6.chunk.js │ │ │ ├── 44.14c338c8.chunk.js │ │ │ ├── 45.eea48cf2.chunk.js │ │ │ ├── 46.ccb35aec.chunk.js │ │ │ ├── 47.3e0688d5.chunk.js │ │ │ ├── 48.db3055a6.chunk.js │ │ │ ├── 49.12cefa9a.chunk.js │ │ │ ├── 50.e05c1b7b.chunk.js │ │ │ ├── 51.29036b60.chunk.js │ │ │ ├── 52.f55e85d8.chunk.js │ │ │ ├── 52.f55e85d8.chunk.js.LICENSE.txt │ │ │ ├── 53.c75cb7a3.chunk.js │ │ │ ├── 54.8714cf50.chunk.js │ │ │ ├── 55.7c013f81.chunk.js │ │ │ ├── 56.babace81.chunk.js │ │ │ ├── 57.25f0137b.chunk.js │ │ │ ├── 58.2b159274.chunk.js │ │ │ ├── 59.ba438755.chunk.js │ │ │ ├── 6.1133d547.chunk.js │ │ │ ├── 60.b4ad5138.chunk.js │ │ │ ├── 61.81768298.chunk.js │ │ │ ├── 62.3060cd66.chunk.js │ │ │ ├── 63.f03c5e55.chunk.js │ │ │ ├── 64.a719b5e4.chunk.js │ │ │ ├── 65.1aee1248.chunk.js │ │ │ ├── 66.620980a9.chunk.js │ │ │ ├── 67.bcd515c8.chunk.js │ │ │ ├── 68.c9ac6468.chunk.js │ │ │ ├── 69.3c7cb39a.chunk.js │ │ │ ├── 7.b7f2a1f8.chunk.js │ │ │ ├── 8.7458a4df.chunk.js │ │ │ ├── 9.a13fb562.chunk.js │ │ │ ├── chunk-vendors.cbc1d7ee.chunk.js │ │ │ ├── chunk-vendors.cbc1d7ee.chunk.js.LICENSE.txt │ │ │ └── index.af4e6410.chunk.js │ ├── css.worker.js │ ├── editor.worker.js │ ├── html.worker.js │ ├── index.html │ ├── json.worker.js │ ├── runtime~index.bundle.js │ ├── sprite-extend-3d.js │ ├── sprite-geo-earth.esm.js │ ├── sprite-geo-earth.js │ ├── sprite-geo-earth.min.js │ ├── spritejs.js │ ├── typescript.worker.js │ └── typescript.worker.js.LICENSE.txt ├── examples │ ├── assets │ │ ├── TB1Jp7dbsjI8KJjSsppXXXbyVXa-9000-4500.jpg │ │ ├── TB1mR3bX3nH8KJjSspcXXb3QFXa-9000-4500.jpg │ │ ├── geodata.json │ │ └── world.json │ ├── b_globe.html │ ├── beam.html │ ├── lib │ │ ├── sprite-extend-3d.js │ │ └── spritejs.js │ ├── mars.html │ ├── normalmap.html │ ├── test.html │ └── with_texture.html ├── package.json ├── src │ ├── beam.js │ ├── camera.js │ ├── config.js │ ├── curve.js │ ├── globe.js │ ├── index.js │ ├── map.js │ ├── marker.js │ ├── missile.js │ └── shaders │ │ ├── beam.frag │ │ ├── beam.vert │ │ ├── corona.frag │ │ ├── corona.vert │ │ ├── curve.frag │ │ ├── curve.vert │ │ ├── globe.frag │ │ ├── globe_normal_map.frag │ │ ├── globe_texture.frag │ │ ├── globe_texture_normal_map.frag │ │ ├── marker.frag │ │ ├── marker.vert │ │ ├── missile.frag │ │ ├── missile.vert │ │ ├── sky.frag │ │ ├── sky.vert │ │ ├── spot.frag │ │ └── spot.vert └── webpack.config.js ├── webgl └── hello_world.html └── webgl_particles ├── app.js └── index.html /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | globals: { 3 | GlRenderer: true, 4 | glDoodle: true, 5 | __DEV__: true 6 | }, 7 | extends: 'eslint-config-sprite', 8 | env: { 9 | browser: true, 10 | mocha: true 11 | }, 12 | plugins: ['html'], 13 | rules: { 14 | complexity: ['warn', 25], 15 | 'import/prefer-default-export': 'off', 16 | 'no-unused-vars': 'warn' 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | node_modules 4 | yarn.lock 5 | package-lock.json 6 | .docz 7 | .nyc_output 8 | coverage 9 | .vscode -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Akira Wu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /animate/animate_delta.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 18 | 19 | 20 |
21 | 29 | 30 | -------------------------------------------------------------------------------- /animate/animate_time.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 18 | 19 | 20 |
21 | 35 | 36 | -------------------------------------------------------------------------------- /animate/animator.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 26 | 27 | 28 |
29 |
30 |
31 |
32 |
33 |
34 | 47 | 48 | -------------------------------------------------------------------------------- /animate/frame_animate.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 帧动画 7 | 27 | 28 | 29 |
30 | 31 | -------------------------------------------------------------------------------- /animate/lerp-bezier-css.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 32 | 33 | 34 |
35 |
36 |
37 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /animate/lerp-bezier.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 25 | 26 | 27 |
28 |
29 |
30 | 31 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /animate/lerp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 25 | 26 | 27 |
28 |
29 |
30 | 41 | 42 | -------------------------------------------------------------------------------- /animate_webgl/lerp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | shader动画 7 | 8 | 9 | 10 | 11 | 70 | 71 | -------------------------------------------------------------------------------- /animate_webgl/lerp_easing.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | shader动画 7 | 8 | 9 | 10 | 11 | 72 | 73 | -------------------------------------------------------------------------------- /assets/airplane.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akira-cn/graphics/019549d65e7818a2f26d3fb9d17a148abb4265d0/assets/airplane.jpg -------------------------------------------------------------------------------- /assets/normal_map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akira-cn/graphics/019549d65e7818a2f26d3fb9d17a148abb4265d0/assets/normal_map.png -------------------------------------------------------------------------------- /assets/normal_plane.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akira-cn/graphics/019549d65e7818a2f26d3fb9d17a148abb4265d0/assets/normal_plane.jpg -------------------------------------------------------------------------------- /assets/rock.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akira-cn/graphics/019549d65e7818a2f26d3fb9d17a148abb4265d0/assets/rock.jpg -------------------------------------------------------------------------------- /assets/rock_normal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akira-cn/graphics/019549d65e7818a2f26d3fb9d17a148abb4265d0/assets/rock_normal.jpg -------------------------------------------------------------------------------- /bezier/app.js: -------------------------------------------------------------------------------- 1 | import {parametric} from '../common/lib/parametric.js'; 2 | import {Vector2D} from '../common/lib/vector2d.js'; 3 | 4 | const canvas = document.querySelector('canvas'); 5 | const ctx = canvas.getContext('2d'); 6 | const {width, height} = canvas; 7 | const w = 0.5 * width, 8 | h = 0.5 * height; 9 | ctx.translate(w, h); 10 | ctx.scale(1, -1); 11 | 12 | function drawAxis() { 13 | ctx.save(); 14 | ctx.strokeStyle = '#ccc'; 15 | ctx.beginPath(); 16 | ctx.moveTo(-w, 0); 17 | ctx.lineTo(w, 0); 18 | ctx.stroke(); 19 | ctx.beginPath(); 20 | ctx.moveTo(0, -h); 21 | ctx.lineTo(0, h); 22 | ctx.stroke(); 23 | ctx.restore(); 24 | } 25 | 26 | drawAxis(); 27 | 28 | const quadricBezier = parametric( 29 | (t, [{x: x0}, {x: x1}, {x: x2}]) => (1 - t) ** 2 * x0 + 2 * t * (1 - t) * x1 + t ** 2 * x2, 30 | (t, [{y: y0}, {y: y1}, {y: y2}]) => (1 - t) ** 2 * y0 + 2 * t * (1 - t) * y1 + t ** 2 * y2, 31 | ); 32 | 33 | const p0 = new Vector2D(0, 0); 34 | const p1 = new Vector2D(100, 0); 35 | p1.rotate(0.75); 36 | const p2 = new Vector2D(200, 0); 37 | const count = 30; 38 | for(let i = 0; i < count; i++) { 39 | p1.rotate(2 / count * Math.PI); 40 | p2.rotate(2 / count * Math.PI); 41 | quadricBezier(0, 1, 100, [ 42 | p0, 43 | p1, 44 | p2, 45 | ]).draw(ctx); 46 | } 47 | -------------------------------------------------------------------------------- /bezier/app2.js: -------------------------------------------------------------------------------- 1 | import {parametric} from '../common/lib/parametric.js'; 2 | import {Vector2D} from '../common/lib/vector2d.js'; 3 | 4 | const canvas = document.querySelector('canvas'); 5 | const ctx = canvas.getContext('2d'); 6 | const {width, height} = canvas; 7 | const w = 0.5 * width, 8 | h = 0.5 * height; 9 | ctx.translate(w, h); 10 | ctx.scale(1, -1); 11 | 12 | function drawAxis() { 13 | ctx.save(); 14 | ctx.strokeStyle = '#ccc'; 15 | ctx.beginPath(); 16 | ctx.moveTo(-w, 0); 17 | ctx.lineTo(w, 0); 18 | ctx.stroke(); 19 | ctx.beginPath(); 20 | ctx.moveTo(0, -h); 21 | ctx.lineTo(0, h); 22 | ctx.stroke(); 23 | ctx.restore(); 24 | } 25 | 26 | drawAxis(); 27 | 28 | const cubicBezier = parametric( 29 | (t, [{x: x0}, {x: x1}, {x: x2}, {x: x3}]) => (1 - t) ** 3 * x0 + 3 * t * (1 - t) ** 2 * x1 + 3 * (1 - t) * t ** 2 * x2 + t ** 3 * x3, 30 | (t, [{y: y0}, {y: y1}, {y: y2}, {y: y3}]) => (1 - t) ** 3 * y0 + 3 * t * (1 - t) ** 2 * y1 + 3 * (1 - t) * t ** 2 * y2 + t ** 3 * y3, 31 | ); 32 | 33 | const p0 = new Vector2D(0, 0); 34 | const p1 = new Vector2D(100, 0); 35 | p1.rotate(0.75); 36 | const p2 = new Vector2D(150, 0); 37 | p2.rotate(-0.75); 38 | const p3 = new Vector2D(200, 0); 39 | const count = 30; 40 | for(let i = 0; i < count; i++) { 41 | p1.rotate(2 / count * Math.PI); 42 | p2.rotate(2 / count * Math.PI); 43 | p3.rotate(2 / count * Math.PI); 44 | cubicBezier(0, 1, 100, [ 45 | p0, 46 | p1, 47 | p2, 48 | p3, 49 | ]).draw(ctx); 50 | } 51 | -------------------------------------------------------------------------------- /bezier/cubic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 贝塞尔曲线 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /bezier/quadratic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 贝塞尔曲线 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /canvas/basic/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Canvas 7 | 12 | 13 | 14 | 15 | 53 | 54 | -------------------------------------------------------------------------------- /canvas/hierarchy/app.js: -------------------------------------------------------------------------------- 1 | const dataSource = 'https://s5.ssl.qhres2.com/static/b0695e2dd30daa64.json'; 2 | 3 | /* globals d3 */ 4 | (async function () { 5 | const data = await (await fetch(dataSource)).json(); 6 | const regions = d3.hierarchy(data) 7 | .sum(d => 1) 8 | .sort((a, b) => b.value - a.value); 9 | 10 | const pack = d3.pack() 11 | .size([1600, 1600]) 12 | .padding(3); 13 | 14 | const root = pack(regions); 15 | 16 | const canvas = document.querySelector('canvas'); 17 | const context = canvas.getContext('2d'); 18 | const TAU = 2 * Math.PI; 19 | 20 | function draw(ctx, node, {fillStyle = 'rgba(0, 0, 0, 0.2)', textColor = 'white'} = {}) { 21 | const children = node.children; 22 | const {x, y, r} = node; 23 | ctx.fillStyle = fillStyle; 24 | ctx.beginPath(); 25 | ctx.arc(x, y, r, 0, TAU); 26 | ctx.fill(); 27 | if(children) { 28 | for(let i = 0; i < children.length; i++) { 29 | draw(context, children[i]); 30 | } 31 | } else { 32 | const name = node.data.name; 33 | ctx.fillStyle = textColor; 34 | ctx.font = '1.5rem Arial'; 35 | ctx.textAlign = 'center'; 36 | ctx.fillText(name, x, y); 37 | } 38 | } 39 | 40 | draw(context, root); 41 | }()); -------------------------------------------------------------------------------- /canvas/hierarchy/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Hierarchy render by canvas 7 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /canvas/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Canvas 7 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /color-hints/app-cubehelix.js: -------------------------------------------------------------------------------- 1 | import {cubehelix} from '../common/lib/color/cubehelix/index.js'; 2 | 3 | const canvas = document.querySelector('canvas'); 4 | const ctx = canvas.getContext('2d'); 5 | 6 | ctx.translate(0, 256); 7 | ctx.scale(1, -1); 8 | 9 | const color = cubehelix(); 10 | const T = 2000; 11 | 12 | function update(t) { 13 | const p = 0.5 + 0.5 * Math.sin(t / T); 14 | ctx.clearRect(0, -256, 512, 512); 15 | const {r, g, b} = color(p); 16 | ctx.fillStyle = `rgb(${255 * r},${255 * g},${255 * b})`; 17 | ctx.beginPath(); 18 | ctx.rect(20, -20, 480 * p, 40); 19 | ctx.fill(); 20 | window.ctx = ctx; 21 | requestAnimationFrame(update); 22 | } 23 | 24 | update(0); -------------------------------------------------------------------------------- /color-hints/app-hsl-problem.js: -------------------------------------------------------------------------------- 1 | const canvas = document.querySelector('canvas'); 2 | const ctx = canvas.getContext('2d'); 3 | 4 | ctx.translate(256, 256); 5 | ctx.scale(1, -1); 6 | 7 | for(let i = 0; i < 20; i++) { 8 | ctx.fillStyle = `hsl(${Math.floor(i * 15)}, 50%, 50%)`; 9 | ctx.beginPath(); 10 | ctx.arc((i - 10) * 20, 60, 10, 0, Math.PI * 2); 11 | ctx.fill(); 12 | } 13 | 14 | for(let i = 0; i < 20; i++) { 15 | ctx.fillStyle = `hsl(${Math.floor((i % 2 ? 60 : 210) + 3 * i)}, 50%, 50%)`; 16 | ctx.beginPath(); 17 | ctx.arc((i - 10) * 20, -60, 10, 0, Math.PI * 2); 18 | ctx.fill(); 19 | } -------------------------------------------------------------------------------- /color-hints/app-hsl.js: -------------------------------------------------------------------------------- 1 | import {Vec3} from '../common/lib/math/Vec3.js'; 2 | const canvas = document.querySelector('canvas'); 3 | const ctx = canvas.getContext('2d'); 4 | 5 | function randomRGB() { 6 | return new Vec3( 7 | 0.5 * Math.random(), 8 | 0.7, 9 | 0.45, 10 | ); 11 | } 12 | 13 | ctx.translate(256, 256); 14 | ctx.scale(1, -1); 15 | 16 | const [h, s, l] = randomRGB(); 17 | for(let i = 0; i < 3; i++) { 18 | const p = (i * 0.25 + h) % 1; 19 | for(let j = 0; j < 5; j++) { 20 | const d = j - 2; 21 | ctx.fillStyle = `hsl(${Math.floor(p * 360)}, ${Math.floor((0.15 * d + s) * 100)}%, ${Math.floor((0.12 * d + l) * 100)}%)`; 22 | ctx.beginPath(); 23 | ctx.arc((j - 2) * 60, (i - 1) * 60, 20, 0, Math.PI * 2); 24 | ctx.fill(); 25 | } 26 | } -------------------------------------------------------------------------------- /color-hints/app-lab.js: -------------------------------------------------------------------------------- 1 | const canvas = document.querySelector('canvas'); 2 | const ctx = canvas.getContext('2d'); 3 | 4 | ctx.translate(256, 256); 5 | ctx.scale(1, -1); 6 | 7 | /* global d3 */ 8 | for(let i = 0; i < 20; i++) { 9 | const c = d3.lab(30, i * 15 - 150, i * 15 - 150).rgb(); 10 | ctx.fillStyle = `rgb(${c.r}, ${c.g}, ${c.b})`; 11 | ctx.beginPath(); 12 | ctx.arc((i - 10) * 20, 60, 10, 0, Math.PI * 2); 13 | ctx.fill(); 14 | } 15 | 16 | for(let i = 0; i < 20; i++) { 17 | const c = d3.lab(i * 5, 80, 80).rgb(); 18 | ctx.fillStyle = `rgb(${c.r}, ${c.g}, ${c.b})`; 19 | ctx.beginPath(); 20 | ctx.arc((i - 10) * 20, -60, 10, 0, Math.PI * 2); 21 | ctx.fill(); 22 | } -------------------------------------------------------------------------------- /color-hints/app-rgb.js: -------------------------------------------------------------------------------- 1 | import {Vec3} from '../common/lib/math/Vec3.js'; 2 | const canvas = document.querySelector('canvas'); 3 | const ctx = canvas.getContext('2d'); 4 | 5 | function randomRGB() { 6 | return new Vec3( 7 | 0.5 * Math.random(), 8 | 0.5 * Math.random(), 9 | 0.5 * Math.random(), 10 | ); 11 | } 12 | 13 | ctx.translate(256, 256); 14 | ctx.scale(1, -1); 15 | 16 | for(let i = 0; i < 3; i++) { 17 | const colorVector = randomRGB(); 18 | for(let j = 0; j < 5; j++) { 19 | const c = colorVector.clone().scale(0.5 + 0.25 * j); 20 | ctx.fillStyle = `rgb(${Math.floor(c[0] * 256)}, ${Math.floor(c[1] * 256)}, ${Math.floor(c[2] * 256)})`; 21 | ctx.beginPath(); 22 | ctx.arc((j - 2) * 60, (i - 1) * 60, 20, 0, Math.PI * 2); 23 | ctx.fill(); 24 | } 25 | } -------------------------------------------------------------------------------- /color-hints/color-cubehelix.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Color hints 7 | 8 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /color-hints/color-hints-hsl.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Color hints 7 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /color-hints/color-hints-rgb.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Color hints 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /color-hints/color-hsl-problem.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Color hints 7 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /color-hints/color-lab.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Color hints 7 | 8 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /common/lib/animator/index.js: -------------------------------------------------------------------------------- 1 | import {Timing} from './timing.js'; 2 | 3 | export class Animator { 4 | constructor({duration, iterations, easing}) { 5 | this.timing = {duration, iterations, easing}; 6 | } 7 | 8 | animate(target, update) { 9 | let frameIndex = 0; 10 | const timing = new Timing(this.timing); 11 | 12 | return new Promise((resolve) => { 13 | function next() { 14 | if(update({target, frameIndex, timing}) !== false && !timing.isFinished) { 15 | requestAnimationFrame(next); 16 | } else { 17 | resolve(timing); 18 | } 19 | frameIndex++; 20 | } 21 | next(); 22 | }); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /common/lib/animator/timing.js: -------------------------------------------------------------------------------- 1 | export class Timing { 2 | constructor({duration, iterations = 1, easing = p => p} = {}) { 3 | this.startTime = Date.now(); 4 | this.duration = duration; 5 | this.iterations = iterations; 6 | this.easing = easing; 7 | } 8 | 9 | get time() { 10 | return Date.now() - this.startTime; 11 | } 12 | 13 | get p() { 14 | const progress = Math.min(this.time / this.duration, this.iterations); 15 | return this.isFinished ? 1 : this.easing(progress % 1); 16 | } 17 | 18 | get isFinished() { 19 | return this.time / this.duration >= this.iterations; 20 | } 21 | } -------------------------------------------------------------------------------- /common/lib/color/cubehelix/index.js: -------------------------------------------------------------------------------- 1 | import {add, multiply, scalarMul} from './matrix.js'; 2 | 3 | const defaultHelixConfig = {start: 0.5, r: -1.5, hue: 1.2, gamma: 1.0}; 4 | 5 | export function cubehelix(overrides = {}) { 6 | const options = Object.assign({}, defaultHelixConfig, overrides); 7 | 8 | const start = options.start; 9 | const r = options.r; 10 | const hue = options.hue; 11 | const gamma = options.gamma; 12 | 13 | return function (l) { 14 | if((l < 0) || (l > 1)) { 15 | throw new Error(`input must be in the [0, 1] range (was: ${l})`); 16 | } 17 | const phi = 2 * Math.PI * (start / 3 + r * l); 18 | const exp = l ** gamma; 19 | const alpha = hue * exp * (1 - exp) / 2; 20 | const rgb = add([[exp], [exp], [exp]], 21 | scalarMul(alpha, multiply([[-0.14861, 1.78277], [-0.29227, -0.90649], [1.97294, 0]], [[Math.cos(phi)], [Math.sin(phi)]]))); 22 | return {r: rgb[0], g: rgb[1], b: rgb[2]}; 23 | }; 24 | } -------------------------------------------------------------------------------- /common/lib/color/cubehelix/matrix.js: -------------------------------------------------------------------------------- 1 | export function add(a, b) { 2 | const dimensions = (() => { 3 | const aNumRows = a.length, 4 | aNumCols = a[0].length; 5 | const bNumRows = b.length, 6 | bNumCols = b[0].length; 7 | if((aNumRows !== bNumRows) && (aNumCols !== bNumCols)) { 8 | throw new Error('matrices differ in dimensions'); 9 | } 10 | return { 11 | nrows: aNumRows, 12 | ncols: aNumCols, 13 | }; 14 | })(); 15 | 16 | const m = new Array(dimensions.nrows); // initialize array of rows 17 | for(let r = 0; r < dimensions.nrows; ++r) { 18 | m[r] = new Array(dimensions.ncols); // initialize the current row 19 | for(let c = 0; c < dimensions.ncols; ++c) { 20 | m[r][c] = a[r][c] + b[r][c]; 21 | } 22 | } 23 | return m; 24 | } 25 | 26 | 27 | export function multiply(a, b) { 28 | const aNumRows = a.length, 29 | aNumCols = a[0].length; 30 | const bNumRows = b.length, 31 | bNumCols = b[0].length; 32 | const m = new Array(aNumRows); // initialize array of rows 33 | for(let r = 0; r < aNumRows; ++r) { 34 | m[r] = new Array(bNumCols); // initialize the current row 35 | for(let c = 0; c < bNumCols; ++c) { 36 | m[r][c] = 0; // initialize the current cell 37 | for(let i = 0; i < aNumCols; ++i) { 38 | m[r][c] += a[r][i] * b[i][c]; 39 | } 40 | } 41 | } 42 | return m; 43 | } 44 | 45 | export function scalarMul(a, matrix) { 46 | const aNumRows = matrix.length; 47 | const aNumCols = matrix[0].length; 48 | const m = new Array(aNumRows); // initialize array of rows 49 | for(let r = 0; r < aNumRows; ++r) { 50 | m[r] = new Array(aNumCols); // initialize the current row 51 | for(let c = 0; c < aNumCols; ++c) { 52 | m[r][c] = a * matrix[r][c]; 53 | } 54 | } 55 | return m; 56 | } 57 | 58 | export function display(m) { 59 | const rv = []; 60 | for(let r = 0; r < m.length; ++r) { 61 | rv.push(m[r].join(' ')); 62 | } 63 | return rv.join('\n'); 64 | } -------------------------------------------------------------------------------- /common/lib/math/Color.js: -------------------------------------------------------------------------------- 1 | import * as ColorFunc from './functions/ColorFunc.js'; 2 | 3 | // Color stored as an array of RGB decimal values (between 0 > 1) 4 | // Constructor and set method accept following formats: 5 | // new Color() - Empty (defaults to black) 6 | // new Color([0.2, 0.4, 1.0]) - Decimal Array (or another Color instance) 7 | // new Color(0.7, 0.0, 0.1) - Decimal RGB values 8 | // new Color('#ff0000') - Hex string 9 | // new Color('#ccc') - Short-hand Hex string 10 | // new Color(0x4f27e8) - Number 11 | // new Color('red') - Color name string (short list in ColorFunc.js) 12 | 13 | export class Color extends Array { 14 | constructor(color) { 15 | if (Array.isArray(color)) return super(...color); 16 | return super(...ColorFunc.parseColor(...arguments)); 17 | } 18 | 19 | get r() { 20 | return this[0]; 21 | } 22 | 23 | get g() { 24 | return this[1]; 25 | } 26 | 27 | get b() { 28 | return this[2]; 29 | } 30 | 31 | set r(v) { 32 | this[0] = v; 33 | } 34 | 35 | set g(v) { 36 | this[1] = v; 37 | } 38 | 39 | set b(v) { 40 | this[2] = v; 41 | } 42 | 43 | set(color) { 44 | if (Array.isArray(color)) return this.copy(color); 45 | return this.copy(ColorFunc.parseColor(...arguments)); 46 | } 47 | 48 | copy(v) { 49 | this[0] = v[0]; 50 | this[1] = v[1]; 51 | this[2] = v[2]; 52 | return this; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /common/lib/math/Euler.js: -------------------------------------------------------------------------------- 1 | import * as EulerFunc from './functions/EulerFunc.js'; 2 | import {Mat4} from './Mat4.js'; 3 | 4 | const tmpMat4 = new Mat4(); 5 | 6 | export class Euler extends Array { 7 | constructor(x = 0, y = x, z = x, order = 'YXZ') { 8 | super(x, y, z); 9 | this.order = order; 10 | this.onChange = () => {}; 11 | return this; 12 | } 13 | 14 | get x() { 15 | return this[0]; 16 | } 17 | 18 | get y() { 19 | return this[1]; 20 | } 21 | 22 | get z() { 23 | return this[2]; 24 | } 25 | 26 | set x(v) { 27 | this[0] = v; 28 | this.onChange(); 29 | } 30 | 31 | set y(v) { 32 | this[1] = v; 33 | this.onChange(); 34 | } 35 | 36 | set z(v) { 37 | this[2] = v; 38 | this.onChange(); 39 | } 40 | 41 | set(x, y = x, z = x) { 42 | if (x.length) return this.copy(x); 43 | this[0] = x; 44 | this[1] = y; 45 | this[2] = z; 46 | this.onChange(); 47 | return this; 48 | } 49 | 50 | copy(v) { 51 | this[0] = v[0]; 52 | this[1] = v[1]; 53 | this[2] = v[2]; 54 | this.onChange(); 55 | return this; 56 | } 57 | 58 | reorder(order) { 59 | this.order = order; 60 | this.onChange(); 61 | return this; 62 | } 63 | 64 | fromRotationMatrix(m, order = this.order) { 65 | EulerFunc.fromRotationMatrix(this, m, order); 66 | return this; 67 | } 68 | 69 | fromQuaternion(q, order = this.order) { 70 | tmpMat4.fromQuaternion(q); 71 | return this.fromRotationMatrix(tmpMat4, order); 72 | } 73 | } -------------------------------------------------------------------------------- /common/lib/math/README.md: -------------------------------------------------------------------------------- 1 | ## 图形学数学工具库 2 | 3 | 来源: https://github.com/oframe/ogl -------------------------------------------------------------------------------- /common/lib/math/Vec4.js: -------------------------------------------------------------------------------- 1 | import * as Vec4Func from './functions/Vec4Func.js'; 2 | 3 | export class Vec4 extends Array { 4 | constructor(x = 0, y = x, z = x, w = x) { 5 | super(x, y, z, w); 6 | return this; 7 | } 8 | 9 | get x() { 10 | return this[0]; 11 | } 12 | 13 | get y() { 14 | return this[1]; 15 | } 16 | 17 | get z() { 18 | return this[2]; 19 | } 20 | 21 | get w() { 22 | return this[3]; 23 | } 24 | 25 | set x(v) { 26 | this[0] = v; 27 | } 28 | 29 | set y(v) { 30 | this[1] = v; 31 | } 32 | 33 | set z(v) { 34 | this[2] = v; 35 | } 36 | 37 | set w(v) { 38 | this[3] = v; 39 | } 40 | 41 | set(x, y, z, w) { 42 | if (x.length) return this.copy(x); 43 | Vec4Func.set(this, x, y, z, w); 44 | return this; 45 | } 46 | 47 | copy(v) { 48 | Vec4Func.copy(this, v); 49 | return this; 50 | } 51 | 52 | normalize() { 53 | Vec4Func.normalize(this, this); 54 | return this; 55 | } 56 | 57 | fromArray(a, o = 0) { 58 | this[0] = a[o]; 59 | this[1] = a[o + 1]; 60 | this[2] = a[o + 2]; 61 | this[3] = a[o + 3]; 62 | return this; 63 | } 64 | 65 | toArray(a = [], o = 0) { 66 | a[o] = this[0]; 67 | a[o + 1] = this[1]; 68 | a[o + 2] = this[2]; 69 | a[o + 3] = this[3]; 70 | return a; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /common/lib/math/functions/ColorFunc.js: -------------------------------------------------------------------------------- 1 | const NAMES = { 2 | "black" : "#000000", 3 | "white" : "#ffffff", 4 | "red" : "#ff0000", 5 | "green" : "#00ff00", 6 | "blue" : "#0000ff", 7 | "fuchsia" : "#ff00ff", 8 | "cyan" : "#00ffff", 9 | "yellow" : "#ffff00", 10 | "orange" : "#ff8000", 11 | }; 12 | 13 | export function hexToRGB(hex) { 14 | if (hex.length === 4) hex = hex[0] + hex[1] + hex[1] + hex[2] + hex[2] + hex[3] + hex[3]; 15 | const rgb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 16 | if (!rgb) console.warn(`Unable to convert hex string ${hex} to rgb values`); 17 | return [ 18 | parseInt(rgb[1], 16) / 255, 19 | parseInt(rgb[2], 16) / 255, 20 | parseInt(rgb[3], 16) / 255 21 | ]; 22 | } 23 | 24 | export function numberToRGB(num) { 25 | num = parseInt(num); 26 | return [ 27 | (num >> 16 & 255) / 255, 28 | (num >> 8 & 255) / 255, 29 | (num & 255) / 255, 30 | ] 31 | } 32 | 33 | export function parseColor(color) { 34 | 35 | // Empty 36 | if (color === undefined) return [0, 0, 0]; 37 | 38 | // Decimal 39 | if (arguments.length === 3) return arguments; 40 | 41 | // Number 42 | if (!isNaN(color)) return numberToRGB(color); 43 | 44 | // Hex 45 | if (color[0] === "#") return hexToRGB(color); 46 | 47 | // Names 48 | if (NAMES[color.toLowerCase()]) return hexToRGB(NAMES[color.toLowerCase()]); 49 | 50 | console.warn('Color format not recognised'); 51 | return [0, 0, 0]; 52 | } 53 | 54 | -------------------------------------------------------------------------------- /common/lib/ogl/extras/Animation.js: -------------------------------------------------------------------------------- 1 | import { Vec3 } from '../math/Vec3.js'; 2 | import { Quat } from '../math/Quat.js'; 3 | 4 | const prevPos = new Vec3(); 5 | const prevRot = new Quat(); 6 | const prevScl = new Vec3(); 7 | 8 | const nextPos = new Vec3(); 9 | const nextRot = new Quat(); 10 | const nextScl = new Vec3(); 11 | 12 | export class Animation { 13 | constructor({ objects, data }) { 14 | this.objects = objects; 15 | this.data = data; 16 | this.elapsed = 0; 17 | this.weight = 1; 18 | this.duration = data.frames.length - 1; 19 | } 20 | 21 | update(totalWeight = 1, isSet) { 22 | const weight = isSet ? 1 : this.weight / totalWeight; 23 | const elapsed = this.elapsed % this.duration; 24 | 25 | const floorFrame = Math.floor(elapsed); 26 | const blend = elapsed - floorFrame; 27 | const prevKey = this.data.frames[floorFrame]; 28 | const nextKey = this.data.frames[(floorFrame + 1) % this.duration]; 29 | 30 | this.objects.forEach((object, i) => { 31 | prevPos.fromArray(prevKey.position, i * 3); 32 | prevRot.fromArray(prevKey.quaternion, i * 4); 33 | prevScl.fromArray(prevKey.scale, i * 3); 34 | 35 | nextPos.fromArray(nextKey.position, i * 3); 36 | nextRot.fromArray(nextKey.quaternion, i * 4); 37 | nextScl.fromArray(nextKey.scale, i * 3); 38 | 39 | prevPos.lerp(nextPos, blend); 40 | prevRot.slerp(nextRot, blend); 41 | prevScl.lerp(nextScl, blend); 42 | 43 | object.position.lerp(prevPos, weight); 44 | object.quaternion.slerp(prevRot, weight); 45 | object.scale.lerp(prevScl, weight); 46 | }); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /common/lib/ogl/extras/NormalProgram.js: -------------------------------------------------------------------------------- 1 | import { Program } from '../core/Program.js'; 2 | 3 | const vertex = /* glsl */ ` 4 | precision highp float; 5 | precision highp int; 6 | 7 | attribute vec3 position; 8 | attribute vec3 normal; 9 | 10 | uniform mat3 normalMatrix; 11 | uniform mat4 modelViewMatrix; 12 | uniform mat4 projectionMatrix; 13 | 14 | varying vec3 vNormal; 15 | 16 | void main() { 17 | vNormal = normalize(normalMatrix * normal); 18 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 19 | } 20 | `; 21 | 22 | const fragment = /* glsl */ ` 23 | precision highp float; 24 | precision highp int; 25 | 26 | varying vec3 vNormal; 27 | 28 | void main() { 29 | gl_FragColor.rgb = normalize(vNormal); 30 | gl_FragColor.a = 1.0; 31 | } 32 | `; 33 | 34 | export function NormalProgram(gl) { 35 | return new Program(gl, { 36 | vertex: vertex, 37 | fragment: fragment, 38 | cullFace: null, 39 | }); 40 | } 41 | -------------------------------------------------------------------------------- /common/lib/ogl/extras/Triangle.js: -------------------------------------------------------------------------------- 1 | import { Geometry } from '../core/Geometry.js'; 2 | 3 | export class Triangle extends Geometry { 4 | constructor(gl, { attributes = {} } = {}) { 5 | Object.assign(attributes, { 6 | position: { size: 2, data: new Float32Array([-1, -1, 3, -1, -1, 3]) }, 7 | uv: { size: 2, data: new Float32Array([0, 0, 2, 0, 0, 2]) }, 8 | }); 9 | 10 | super(gl, attributes); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /common/lib/ogl/index.mjs: -------------------------------------------------------------------------------- 1 | // Core 2 | export { Geometry } from './core/Geometry.js'; 3 | export { Program } from './core/Program.js'; 4 | export { Renderer } from './core/Renderer.js'; 5 | export { Camera } from './core/Camera.js'; 6 | export { Transform } from './core/Transform.js'; 7 | export { Mesh } from './core/Mesh.js'; 8 | export { Texture } from './core/Texture.js'; 9 | export { RenderTarget } from './core/RenderTarget.js'; 10 | 11 | // Maths 12 | export { Color } from './math/Color.js'; 13 | export { Euler } from './math/Euler.js'; 14 | export { Mat3 } from './math/Mat3.js'; 15 | export { Mat4 } from './math/Mat4.js'; 16 | export { Quat } from './math/Quat.js'; 17 | export { Vec2 } from './math/Vec2.js'; 18 | export { Vec3 } from './math/Vec3.js'; 19 | export { Vec4 } from './math/Vec4.js'; 20 | 21 | // Extras 22 | export { Plane } from './extras/Plane.js'; 23 | export { Box } from './extras/Box.js'; 24 | export { Sphere } from './extras/Sphere.js'; 25 | export { Cylinder } from './extras/Cylinder.js'; 26 | export { Triangle } from './extras/Triangle.js'; 27 | export { Torus } from './extras/Torus.js'; 28 | export { Orbit } from './extras/Orbit.js'; 29 | export { Raycast } from './extras/Raycast.js'; 30 | export { Curve } from './extras/Curve.js'; 31 | export { Post } from './extras/Post.js'; 32 | export { Skin } from './extras/Skin.js'; 33 | export { Animation } from './extras/Animation.js'; 34 | export { Text } from './extras/Text.js'; 35 | export { NormalProgram } from './extras/NormalProgram.js'; 36 | export { Flowmap } from './extras/Flowmap.js'; 37 | export { GPGPU } from './extras/GPGPU.js'; 38 | export { Polyline } from './extras/Polyline.js'; 39 | export { Shadow } from './extras/Shadow.js'; 40 | export { KTXTexture } from './extras/KTXTexture.js'; 41 | export { TextureLoader } from './extras/TextureLoader.js'; 42 | export { GLTFLoader } from './extras/GLTFLoader.js'; 43 | -------------------------------------------------------------------------------- /common/lib/ogl/math/Color.js: -------------------------------------------------------------------------------- 1 | import * as ColorFunc from './functions/ColorFunc.js'; 2 | 3 | // Color stored as an array of RGB decimal values (between 0 > 1) 4 | // Constructor and set method accept following formats: 5 | // new Color() - Empty (defaults to black) 6 | // new Color([0.2, 0.4, 1.0]) - Decimal Array (or another Color instance) 7 | // new Color(0.7, 0.0, 0.1) - Decimal RGB values 8 | // new Color('#ff0000') - Hex string 9 | // new Color('#ccc') - Short-hand Hex string 10 | // new Color(0x4f27e8) - Number 11 | // new Color('red') - Color name string (short list in ColorFunc.js) 12 | 13 | export class Color extends Array { 14 | constructor(color) { 15 | if (Array.isArray(color)) return super(...color); 16 | return super(...ColorFunc.parseColor(...arguments)); 17 | } 18 | 19 | get r() { 20 | return this[0]; 21 | } 22 | 23 | get g() { 24 | return this[1]; 25 | } 26 | 27 | get b() { 28 | return this[2]; 29 | } 30 | 31 | set r(v) { 32 | this[0] = v; 33 | } 34 | 35 | set g(v) { 36 | this[1] = v; 37 | } 38 | 39 | set b(v) { 40 | this[2] = v; 41 | } 42 | 43 | set(color) { 44 | if (Array.isArray(color)) return this.copy(color); 45 | return this.copy(ColorFunc.parseColor(...arguments)); 46 | } 47 | 48 | copy(v) { 49 | this[0] = v[0]; 50 | this[1] = v[1]; 51 | this[2] = v[2]; 52 | return this; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /common/lib/ogl/math/Euler.js: -------------------------------------------------------------------------------- 1 | import * as EulerFunc from './functions/EulerFunc.js'; 2 | import { Mat4 } from './Mat4.js'; 3 | 4 | const tmpMat4 = new Mat4(); 5 | 6 | export class Euler extends Array { 7 | constructor(x = 0, y = x, z = x, order = 'YXZ') { 8 | super(x, y, z); 9 | this.order = order; 10 | this.onChange = () => {}; 11 | return this; 12 | } 13 | 14 | get x() { 15 | return this[0]; 16 | } 17 | 18 | get y() { 19 | return this[1]; 20 | } 21 | 22 | get z() { 23 | return this[2]; 24 | } 25 | 26 | set x(v) { 27 | this[0] = v; 28 | this.onChange(); 29 | } 30 | 31 | set y(v) { 32 | this[1] = v; 33 | this.onChange(); 34 | } 35 | 36 | set z(v) { 37 | this[2] = v; 38 | this.onChange(); 39 | } 40 | 41 | set(x, y = x, z = x) { 42 | if (x.length) return this.copy(x); 43 | this[0] = x; 44 | this[1] = y; 45 | this[2] = z; 46 | this.onChange(); 47 | return this; 48 | } 49 | 50 | copy(v) { 51 | this[0] = v[0]; 52 | this[1] = v[1]; 53 | this[2] = v[2]; 54 | this.onChange(); 55 | return this; 56 | } 57 | 58 | reorder(order) { 59 | this.order = order; 60 | this.onChange(); 61 | return this; 62 | } 63 | 64 | fromRotationMatrix(m, order = this.order) { 65 | EulerFunc.fromRotationMatrix(this, m, order); 66 | return this; 67 | } 68 | 69 | fromQuaternion(q, order = this.order) { 70 | tmpMat4.fromQuaternion(q); 71 | return this.fromRotationMatrix(tmpMat4, order); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /common/lib/ogl/math/Mat3.js: -------------------------------------------------------------------------------- 1 | import * as Mat3Func from './functions/Mat3Func.js'; 2 | 3 | export class Mat3 extends Array { 4 | constructor(m00 = 1, m01 = 0, m02 = 0, m10 = 0, m11 = 1, m12 = 0, m20 = 0, m21 = 0, m22 = 1) { 5 | super(m00, m01, m02, m10, m11, m12, m20, m21, m22); 6 | return this; 7 | } 8 | 9 | set(m00, m01, m02, m10, m11, m12, m20, m21, m22) { 10 | if (m00.length) return this.copy(m00); 11 | Mat3Func.set(this, m00, m01, m02, m10, m11, m12, m20, m21, m22); 12 | return this; 13 | } 14 | 15 | translate(v, m = this) { 16 | Mat3Func.translate(this, m, v); 17 | return this; 18 | } 19 | 20 | rotate(v, m = this) { 21 | Mat3Func.rotate(this, m, v); 22 | return this; 23 | } 24 | 25 | scale(v, m = this) { 26 | Mat3Func.scale(this, m, v); 27 | return this; 28 | } 29 | 30 | multiply(ma, mb) { 31 | if (mb) { 32 | Mat3Func.multiply(this, ma, mb); 33 | } else { 34 | Mat3Func.multiply(this, this, ma); 35 | } 36 | return this; 37 | } 38 | 39 | identity() { 40 | Mat3Func.identity(this); 41 | return this; 42 | } 43 | 44 | copy(m) { 45 | Mat3Func.copy(this, m); 46 | return this; 47 | } 48 | 49 | fromMatrix4(m) { 50 | Mat3Func.fromMat4(this, m); 51 | return this; 52 | } 53 | 54 | fromQuaternion(q) { 55 | Mat3Func.fromQuat(this, q); 56 | return this; 57 | } 58 | 59 | fromBasis(vec3a, vec3b, vec3c) { 60 | this.set(vec3a[0], vec3a[1], vec3a[2], vec3b[0], vec3b[1], vec3b[2], vec3c[0], vec3c[1], vec3c[2]); 61 | return this; 62 | } 63 | 64 | inverse(m = this) { 65 | Mat3Func.invert(this, m); 66 | return this; 67 | } 68 | 69 | getNormalMatrix(m) { 70 | Mat3Func.normalFromMat4(this, m); 71 | return this; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /common/lib/ogl/math/Vec4.js: -------------------------------------------------------------------------------- 1 | import * as Vec4Func from './functions/Vec4Func.js'; 2 | 3 | export class Vec4 extends Array { 4 | constructor(x = 0, y = x, z = x, w = x) { 5 | super(x, y, z, w); 6 | return this; 7 | } 8 | 9 | get x() { 10 | return this[0]; 11 | } 12 | 13 | get y() { 14 | return this[1]; 15 | } 16 | 17 | get z() { 18 | return this[2]; 19 | } 20 | 21 | get w() { 22 | return this[3]; 23 | } 24 | 25 | set x(v) { 26 | this[0] = v; 27 | } 28 | 29 | set y(v) { 30 | this[1] = v; 31 | } 32 | 33 | set z(v) { 34 | this[2] = v; 35 | } 36 | 37 | set w(v) { 38 | this[3] = v; 39 | } 40 | 41 | set(x, y, z, w) { 42 | if (x.length) return this.copy(x); 43 | Vec4Func.set(this, x, y, z, w); 44 | return this; 45 | } 46 | 47 | copy(v) { 48 | Vec4Func.copy(this, v); 49 | return this; 50 | } 51 | 52 | normalize() { 53 | Vec4Func.normalize(this, this); 54 | return this; 55 | } 56 | 57 | fromArray(a, o = 0) { 58 | this[0] = a[o]; 59 | this[1] = a[o + 1]; 60 | this[2] = a[o + 2]; 61 | this[3] = a[o + 3]; 62 | return this; 63 | } 64 | 65 | toArray(a = [], o = 0) { 66 | a[o] = this[0]; 67 | a[o + 1] = this[1]; 68 | a[o + 2] = this[2]; 69 | a[o + 3] = this[3]; 70 | return a; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /common/lib/ogl/math/functions/ColorFunc.js: -------------------------------------------------------------------------------- 1 | const NAMES = { 2 | black: '#000000', 3 | white: '#ffffff', 4 | red: '#ff0000', 5 | green: '#00ff00', 6 | blue: '#0000ff', 7 | fuchsia: '#ff00ff', 8 | cyan: '#00ffff', 9 | yellow: '#ffff00', 10 | orange: '#ff8000', 11 | }; 12 | 13 | export function hexToRGB(hex) { 14 | if (hex.length === 4) hex = hex[0] + hex[1] + hex[1] + hex[2] + hex[2] + hex[3] + hex[3]; 15 | const rgb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 16 | if (!rgb) console.warn(`Unable to convert hex string ${hex} to rgb values`); 17 | return [parseInt(rgb[1], 16) / 255, parseInt(rgb[2], 16) / 255, parseInt(rgb[3], 16) / 255]; 18 | } 19 | 20 | export function numberToRGB(num) { 21 | num = parseInt(num); 22 | return [((num >> 16) & 255) / 255, ((num >> 8) & 255) / 255, (num & 255) / 255]; 23 | } 24 | 25 | export function parseColor(color) { 26 | // Empty 27 | if (color === undefined) return [0, 0, 0]; 28 | 29 | // Decimal 30 | if (arguments.length === 3) return arguments; 31 | 32 | // Number 33 | if (!isNaN(color)) return numberToRGB(color); 34 | 35 | // Hex 36 | if (color[0] === '#') return hexToRGB(color); 37 | 38 | // Names 39 | if (NAMES[color.toLowerCase()]) return hexToRGB(NAMES[color.toLowerCase()]); 40 | 41 | console.warn('Color format not recognised'); 42 | return [0, 0, 0]; 43 | } 44 | -------------------------------------------------------------------------------- /common/lib/parametric.js: -------------------------------------------------------------------------------- 1 | function draw(points, context, { 2 | strokeStyle = 'black', 3 | fillStyle = null, 4 | close = false, 5 | } = {}) { 6 | context.strokeStyle = strokeStyle; 7 | context.beginPath(); 8 | context.moveTo(...points[0]); 9 | for(let i = 1; i < points.length; i++) { 10 | context.lineTo(...points[i]); 11 | } 12 | if(close) context.closePath(); 13 | if(fillStyle) { 14 | context.fillStyle = fillStyle; 15 | context.fill(); 16 | } 17 | context.stroke(); 18 | } 19 | 20 | 21 | export function parametric(sFunc, tFunc, rFunc) { 22 | return function (start, end, seg = 100, ...args) { 23 | const points = []; 24 | for(let i = 0; i <= seg; i++) { 25 | const p = i / seg; 26 | const t = start * (1 - p) + end * p; 27 | const x = sFunc(t, ...args); 28 | const y = tFunc(t, ...args); 29 | if(rFunc) { 30 | points.push(rFunc(x, y)); 31 | } else { 32 | points.push([x, y]); 33 | } 34 | } 35 | return { 36 | draw: draw.bind(null, points), 37 | points, 38 | }; 39 | }; 40 | } -------------------------------------------------------------------------------- /common/lib/vector2d.js: -------------------------------------------------------------------------------- 1 | export class Vector2D extends Array { 2 | constructor(x = 1, y = 0) { 3 | super(x, y); 4 | } 5 | 6 | set x(v) { 7 | this[0] = v; 8 | } 9 | 10 | set y(v) { 11 | this[1] = v; 12 | } 13 | 14 | get x() { 15 | return this[0]; 16 | } 17 | 18 | get y() { 19 | return this[1]; 20 | } 21 | 22 | get length() { 23 | return Math.hypot(this.x, this.y); 24 | } 25 | 26 | get dir() { 27 | return Math.atan2(this.y, this.x); 28 | } 29 | 30 | copy() { 31 | return new Vector2D(this.x, this.y); 32 | } 33 | 34 | add(v) { 35 | this.x += v.x; 36 | this.y += v.y; 37 | return this; 38 | } 39 | 40 | sub(v) { 41 | this.x -= v.x; 42 | this.y -= v.y; 43 | return this; 44 | } 45 | 46 | scale(a) { 47 | this.x *= a; 48 | this.y *= a; 49 | return this; 50 | } 51 | 52 | cross(v) { 53 | return this.x * v.y - v.x * this.y; 54 | } 55 | 56 | dot(v) { 57 | return this.x * v.x + v.y * this.y; 58 | } 59 | 60 | normalize() { 61 | return this.scale(1 / this.length); 62 | } 63 | 64 | rotate(rad) { 65 | const c = Math.cos(rad), 66 | s = Math.sin(rad); 67 | const [x, y] = this; 68 | 69 | this.x = x * c + y * -s; 70 | this.y = x * s + y * c; 71 | 72 | return this; 73 | } 74 | } -------------------------------------------------------------------------------- /coordinates/app.js: -------------------------------------------------------------------------------- 1 | /* globals rough */ 2 | const rc = rough.canvas(document.querySelector('canvas')); 3 | const ctx = rc.ctx; 4 | ctx.translate(256, 256); 5 | ctx.scale(1, -1); 6 | 7 | const hillOpts = {roughness: 2.8, strokeWidth: 2, fill: 'blue'}; 8 | 9 | rc.path('M-180 0L-80 100L20 0', hillOpts); 10 | rc.path('M-20 0L80 100L180 0', hillOpts); 11 | 12 | rc.circle(0, 150, 105, { 13 | stroke: 'red', 14 | strokeWidth: 4, 15 | fill: 'rgba(255,255, 0, 0.4)', 16 | fillStyle: 'solid', 17 | }); 18 | 19 | // console.log(rc); 20 | 21 | // rc.path('M76 256L176 156L276 256', hillOpts); 22 | // rc.path('M236 256L336 156L436 256', hillOpts); 23 | 24 | // rc.circle(256, 106, 105, { 25 | // stroke: 'red', 26 | // strokeWidth: 4, 27 | // fill: 'rgba(255,255,0,0.4)', 28 | // fillStyle: 'solid', 29 | // }); -------------------------------------------------------------------------------- /coordinates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 坐标系 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /covid-vis/assets/data/t01cd3ca6de977c52a9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akira-cn/graphics/019549d65e7818a2f26d3fb9d17a148abb4265d0/covid-vis/assets/data/t01cd3ca6de977c52a9.jpg -------------------------------------------------------------------------------- /covid-vis/mercator.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Mercator Demo 7 | 8 | 9 | 10 | 56 | 57 | -------------------------------------------------------------------------------- /d3/d3-dom.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 17 | 18 | 19 | 20 | 37 | 38 | -------------------------------------------------------------------------------- /d3/d3-spritejs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 17 | 18 | 19 |
20 | 21 | 22 | 49 | 50 | -------------------------------------------------------------------------------- /data-graph-css/areagraph.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Bar graph 7 | 45 | 46 | 47 |
48 |
49 | 50 | -------------------------------------------------------------------------------- /data-graph-css/bargraph.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Bar graph 7 | 44 | 45 | 46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | 54 | -------------------------------------------------------------------------------- /data-graph-css/linegraph.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Bar graph 7 | 54 | 55 | 56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | 64 | -------------------------------------------------------------------------------- /data-graph-css/piegraph.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Pie graph 7 | 16 | 17 | 18 |
19 |
20 | 21 | -------------------------------------------------------------------------------- /data-graph-svg/bargraph.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Bar graph 7 | 8 | 9 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /data/weather.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akira-cn/graphics/019549d65e7818a2f26d3fb9d17a148abb4265d0/data/weather.zip -------------------------------------------------------------------------------- /data/weather/index1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 天气 2014 7 | 8 | 9 |
10 | 11 | 12 | 13 | 46 | 47 | -------------------------------------------------------------------------------- /data/weather/index3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 天气 2014 7 | 8 | 9 |
10 | 11 | 12 | 13 | 54 | 55 | -------------------------------------------------------------------------------- /data/weather/index4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 天气 2014 7 | 8 | 9 |
10 | 11 | 12 | 13 | 54 | 55 | -------------------------------------------------------------------------------- /data/weather/index6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 天气 2014 7 | 8 | 9 |
10 | 11 | 12 | 13 | 54 | 55 | -------------------------------------------------------------------------------- /gl-raffle/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 抽奖 8 | 19 | 20 | 21 |
22 | 23 | 48 | 49 | -------------------------------------------------------------------------------- /gl-raffle/lib/fragment.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | highp float random(vec2 co) { 6 | highp float a = 12.9898; 7 | highp float b = 78.233; 8 | highp float c = 43758.5453; 9 | highp float dt= dot(co.xy ,vec2(a,b)); 10 | highp float sn= mod(dt,3.14); 11 | return fract(sin(sn) * c); 12 | } 13 | 14 | uniform vec2 resolution; 15 | uniform float rate; 16 | uniform float seed; 17 | 18 | uniform sampler2D texture; 19 | varying vec2 vTextureCoord; 20 | 21 | void main() { 22 | vec2 st = gl_FragCoord.xy / resolution; 23 | st = floor(10.0 * st); 24 | float p = random(st + seed); 25 | p = 1.0 - step(rate, p); 26 | 27 | vec2 texCoord = vec2(vTextureCoord.x, 1.0 - vTextureCoord.y); 28 | vec4 texColor = texture2D(texture, texCoord); 29 | 30 | gl_FragColor = texColor + vec4(0, 0, 1.0, 1.0) * (1.0 - sign(length(texColor.rgb))) * p; 31 | } -------------------------------------------------------------------------------- /gl-raffle/lib/members.js: -------------------------------------------------------------------------------- 1 | export default ` 2 | 萌能量女王 3 | ™吃货小公举~ 4 | 蜜心萝莉酱だ 5 | 5星级萌妹 6 | 来自喵星的少女ᕕ↣ 7 | 国民小仙女 8 | 捣蛋淑女 9 | 喵小萌�喵~ 10 | 糯米团子♡ 11 | 无敌元气妹 12 | 半呆半萌半幼稚 13 | 调皮的小乖比 14 | 装萌小可爱℡ 15 | 任性小孩 16 | 上帝的宠儿 17 | 娇气的小奶包 18 | 暖心萌菇凉 19 | 一阵可爱风 20 | 稚气少女♡ 21 | ↘撒娇是种艺术 22 | 爱哭鬼丫头 23 | 闪开我要发光了 24 | 天然萌女可爱范 25 | 可爱少女撅屁屁^﹏^ 26 | 幼稚园萌小疯 27 | 神经一样的妞 28 | 典型小二货 29 | 天生萌货 30 | 萌酱か小精灵 31 | 喵星人的软女 32 | 幼懵少女 33 | 猫腻少女抱 34 | 俏皮可爱小笨蛋 35 | 佩奇♀女孩 36 | 甜味超标♡ 37 | 十秒萌定你♡ 38 | 来一碗小仙女 39 | ╰呆♔萌↞小不点 40 | 樱桃小软妹 41 | 做梦的季节 42 | “野蛮小可爱° 43 | 绿柠萌岁月 44 | 小跑追幸福╮ 45 | 可爱专属于你 46 | 放任的撒娇 47 | 好奇宝宝! 48 | 古怪软萌妹 49 | 紫色蒲公英 50 | 寂静清棃 51 | 蜜桃色的你ぎ 52 | 柚夏^粉红 53 | 橙色少年 54 | 栀子香气 55 | 柠檬心〆微酸 56 | 青柠滋味 57 | 风扬起思念 58 | 清风伊犁人 59 | 茶~~余香 60 | 淡蓝色回忆 61 | 九月旅途 - 62 | 柠檬薄荷香 63 | 短短的忧伤 64 | 清心一夏 65 | 微雨渐凉 66 | 渐落夕阳 67 | 漫天飞舞的花 68 | 细花微雨 69 | 斜阳柳梢头 70 | 夏至未至 71 | 再见,單調┈o 72 | 水花中的笑脸° 73 | 冰雨微凉 74 | 半岛弥音 75 | 掌心痣 76 | 抓住夏天 77 | 彼岸小路.. 78 | 巴黎风吹拂樱花 79 | 雨中的花伞 80 | 衍夏寂寥 81 | ˇ花语靡靡 82 | 回味_旧时光 83 | 梦回浅唱 84 | 木棉的春很远 85 | 蜜桃微甜 86 | 日落之后 87 | 梨花雨如丝 88 | 花开一场梦 89 | 薄荷蓝 90 | ゛半度浅夏ら 91 | 新鮮感 ぃ 92 | 灬格子秋季 93 | ゆ半夏伊人 94 | 水清山碧 95 | 凉心少女 96 | 勾勾手指许愿 97 | 秘密在心间 98 | 深蓝的心 99 | 夏花一点 100 | 潮汐溢满心 101 | 雨后彩虹天 102 | `.trim().split(/\s+/g); -------------------------------------------------------------------------------- /gl-raffle/lib/prizes.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | {name: 'OMG!买它!!买它!!!' , count: 8}, 3 | {name: '来左边跟我一起画个龙 在你右边画一道彩虹' , count: 2}, 4 | {name: '咸鱼翻身奖' , count: 8}, 5 | {name: '不忘初心,好人一生平安' , count: 1}, 6 | {name: '就是想让你中个奖' , count: 8}, 7 | {name: '生活给你的扑面而来的惊喜' , count: 2}, 8 | {name: '全年无人关爱年会照顾一下' , count: 8}, 9 | {name: '百因必有果,你的报应就是我' , count: 5}, 10 | {name: '反正闲着也是闲着,不如甜一下' , count: 8}, 11 | ]; 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "graphics", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "http-server -c-1 -p9090", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "MIT", 13 | "devDependencies": { 14 | "eslint": "^6.8.0", 15 | "eslint-config-sprite": "^1.0.6", 16 | "eslint-plugin-html": "^6.0.0", 17 | "http-server": "^0.12.1" 18 | }, 19 | "dependencies": { 20 | "rough": "^3.0.1" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /parametric-polar/app.js: -------------------------------------------------------------------------------- 1 | import {parametric} from '../common/lib/parametric.js'; 2 | 3 | const canvas = document.querySelector('canvas'); 4 | const ctx = canvas.getContext('2d'); 5 | const {width, height} = canvas; 6 | const w = 0.5 * width, 7 | h = 0.5 * height; 8 | ctx.translate(w, h); 9 | ctx.scale(1, -1); 10 | 11 | function drawAxis() { 12 | ctx.save(); 13 | ctx.strokeStyle = '#ccc'; 14 | ctx.beginPath(); 15 | ctx.moveTo(-w, 0); 16 | ctx.lineTo(w, 0); 17 | ctx.stroke(); 18 | ctx.beginPath(); 19 | ctx.moveTo(0, -h); 20 | ctx.lineTo(0, h); 21 | ctx.stroke(); 22 | ctx.restore(); 23 | } 24 | 25 | drawAxis(); 26 | 27 | const fromPolar = (r, theta) => { 28 | return [r * Math.cos(theta), r * Math.sin(theta)]; 29 | }; 30 | 31 | const arc = parametric( 32 | t => 200, 33 | t => t, 34 | fromPolar, 35 | ); 36 | 37 | arc(0, Math.PI).draw(ctx); 38 | 39 | const rose = parametric( 40 | (t, a, k) => a * Math.cos(k * t), 41 | t => t, 42 | fromPolar, 43 | ); 44 | 45 | rose(0, Math.PI, 100, 200, 5).draw(ctx, {strokeStyle: 'blue'}); 46 | 47 | const heart = parametric( 48 | (t, a) => a - a * Math.sin(t), 49 | t => t, 50 | fromPolar, 51 | ); 52 | 53 | heart(0, 2 * Math.PI, 100, 100).draw(ctx, {strokeStyle: 'red'}); 54 | 55 | const foliumRight = parametric( 56 | (t, a) => Math.sqrt(2 * a ** 2 * Math.cos(2 * t)), 57 | t => t, 58 | fromPolar, 59 | ); 60 | 61 | const foliumLeft = parametric( 62 | (t, a) => -Math.sqrt(2 * a ** 2 * Math.cos(2 * t)), 63 | t => t, 64 | fromPolar, 65 | ); 66 | 67 | foliumRight(-Math.PI / 4, Math.PI / 4, 100, 100).draw(ctx, {strokeStyle: 'green'}); 68 | foliumLeft(-Math.PI / 4, Math.PI / 4, 100, 100).draw(ctx, {strokeStyle: 'green'}); -------------------------------------------------------------------------------- /parametric-polar/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 极坐标方程 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /parametric/app.js: -------------------------------------------------------------------------------- 1 | const canvas = document.querySelector('canvas'); 2 | const ctx = canvas.getContext('2d'); 3 | const {width, height} = canvas; 4 | ctx.translate(0.5 * width, 0.5 * height); 5 | ctx.scale(1, -1); 6 | 7 | function draw(points, strokeStyle = 'black', fillStyle = null) { 8 | ctx.strokeStyle = strokeStyle; 9 | ctx.beginPath(); 10 | ctx.moveTo(...points[0]); 11 | for(let i = 1; i < points.length; i++) { 12 | ctx.lineTo(...points[i]); 13 | } 14 | ctx.closePath(); 15 | if(fillStyle) { 16 | ctx.fillStyle = fillStyle; 17 | ctx.fill(); 18 | } 19 | ctx.stroke(); 20 | } 21 | 22 | const TAU_SEGMENTS = 60; 23 | const TAU = Math.PI * 2; 24 | function arc(x0, y0, radius, startAng = 0, endAng = Math.PI * 2) { 25 | const ang = Math.min(TAU, endAng - startAng); 26 | const ret = ang === TAU ? [] : [[x0, y0]]; 27 | const segments = Math.round(TAU_SEGMENTS * ang / TAU); 28 | for(let i = 0; i <= segments; i++) { 29 | const x = x0 + radius * Math.cos(startAng + ang * i / segments); 30 | const y = y0 + radius * Math.sin(startAng + ang * i / segments); 31 | ret.push([x, y]); 32 | } 33 | return ret; 34 | } 35 | 36 | draw(arc(0, 0, 100)); -------------------------------------------------------------------------------- /parametric/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 参数方程 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /parametric2/app.js: -------------------------------------------------------------------------------- 1 | import {parametric} from '../common/lib/parametric.js'; 2 | 3 | const canvas = document.querySelector('canvas'); 4 | const ctx = canvas.getContext('2d'); 5 | const {width, height} = canvas; 6 | const w = 0.5 * width, 7 | h = 0.5 * height; 8 | ctx.translate(w, h); 9 | ctx.scale(1, -1); 10 | 11 | function drawAxis() { 12 | ctx.save(); 13 | ctx.strokeStyle = '#ccc'; 14 | ctx.beginPath(); 15 | ctx.moveTo(-w, 0); 16 | ctx.lineTo(w, 0); 17 | ctx.stroke(); 18 | ctx.beginPath(); 19 | ctx.moveTo(0, -h); 20 | ctx.lineTo(0, h); 21 | ctx.stroke(); 22 | ctx.restore(); 23 | } 24 | 25 | drawAxis(); 26 | 27 | const para = parametric( 28 | t => 25 * t, 29 | t => 25 * t ** 2, 30 | ); 31 | 32 | para(-5.5, 5.5).draw(ctx); 33 | 34 | const helical = parametric( 35 | (t, l) => l * t * Math.cos(t), 36 | (t, l) => l * t * Math.sin(t), 37 | ); 38 | 39 | helical(0, 50, 500, 5).draw(ctx, {strokeStyle: 'blue'}); 40 | 41 | const star = parametric( 42 | (t, l) => l * Math.cos(t) ** 3, 43 | (t, l) => l * Math.sin(t) ** 3, 44 | ); 45 | 46 | star(0, Math.PI * 2, 50, 150).draw(ctx, {strokeStyle: 'red'}); -------------------------------------------------------------------------------- /parametric2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 参数方程 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /performance-basic/canvas-circles.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Canvas性能 7 | 14 | 15 | 16 | 17 | 50 | 51 | -------------------------------------------------------------------------------- /performance-basic/svg-circles.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Canvas性能 7 | 14 | 15 | 16 | 17 | 55 | 56 | -------------------------------------------------------------------------------- /performance-more/point-primitives-circle.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Spots 7 | 8 | 9 | 10 | 11 | 57 | 58 | -------------------------------------------------------------------------------- /performance-more/point-primitives-rect.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Spots 7 | 8 | 9 | 10 | 11 | 46 | 47 | -------------------------------------------------------------------------------- /performance_canvas/random_shapes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 随机图形 7 | 8 | 9 | 10 | 54 | 55 | -------------------------------------------------------------------------------- /performance_canvas/random_shapes_optimized.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 随机图形 7 | 8 | 9 | 10 | 63 | 64 | -------------------------------------------------------------------------------- /performance_canvas/random_shapes_worker.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 随机图形 7 | 8 | 9 | 10 | 20 | 21 | -------------------------------------------------------------------------------- /pixels/assets/explode.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akira-cn/graphics/019549d65e7818a2f26d3fb9d17a148abb4265d0/pixels/assets/explode.jpg -------------------------------------------------------------------------------- /pixels/assets/girl1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akira-cn/graphics/019549d65e7818a2f26d3fb9d17a148abb4265d0/pixels/assets/girl1.jpg -------------------------------------------------------------------------------- /pixels/assets/girl2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akira-cn/graphics/019549d65e7818a2f26d3fb9d17a148abb4265d0/pixels/assets/girl2.jpg -------------------------------------------------------------------------------- /pixels/assets/girl3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akira-cn/graphics/019549d65e7818a2f26d3fb9d17a148abb4265d0/pixels/assets/girl3.jpg -------------------------------------------------------------------------------- /pixels/assets/sunlight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akira-cn/graphics/019549d65e7818a2f26d3fb9d17a148abb4265d0/pixels/assets/sunlight.png -------------------------------------------------------------------------------- /pixels/index1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 像素处理 8 | 9 | 10 | 11 | 51 | 52 | -------------------------------------------------------------------------------- /pixels/index2-3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 像素处理 8 | 9 | 10 | 11 | 29 | 30 | -------------------------------------------------------------------------------- /pixels/index2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 像素处理 8 | 9 | 10 | 11 | 31 | 32 | -------------------------------------------------------------------------------- /pixels/index3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 像素处理 8 | 9 | 10 | 11 | 37 | 38 | -------------------------------------------------------------------------------- /pixels/index4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 像素处理 8 | 9 | 10 | 11 | 37 | 38 | -------------------------------------------------------------------------------- /pixels/index5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 像素处理 8 | 9 | 10 | 11 | 35 | 36 | -------------------------------------------------------------------------------- /pixels/index6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 像素处理 8 | 9 | 10 | 11 | 37 | 38 | -------------------------------------------------------------------------------- /pixels/index7.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 像素处理 8 | 9 | 10 | 11 | 32 | 33 | -------------------------------------------------------------------------------- /pixels/lib/image-data.js: -------------------------------------------------------------------------------- 1 | const _data = Symbol('data'); 2 | 3 | export default class ImageData { 4 | constructor(image, rect = [0, 0, image.width, image.height]) { 5 | const canvas = new OffscreenCanvas(image.width, image.height); 6 | const context = canvas.getContext('2d'); 7 | context.drawImage(image, 0, 0); 8 | const imgData = context.getImageData(...rect); 9 | this[_data] = imgData; 10 | } 11 | 12 | get data() { 13 | return this[_data].data; 14 | } 15 | 16 | get width() { 17 | return this[_data].width; 18 | } 19 | 20 | get height() { 21 | return this[_data].height; 22 | } 23 | 24 | getPixel(x, y) { 25 | const {width, height, data} = this; 26 | if(x < 0 || y < 0 || x >= width || y >= height) { 27 | return null; 28 | } 29 | const idx = 4 * (y * width + x); 30 | const r = data[idx] / 255, 31 | g = data[idx + 1] / 255, 32 | b = data[idx + 2] / 255, 33 | a = data[idx + 3] / 255; 34 | return [r, g, b, a]; 35 | } 36 | 37 | * getPixelsByRow(y) { 38 | const {width, height} = this; 39 | if(y < 0 || y >= height) return null; 40 | 41 | for(let i = 0; i < width; i++) { 42 | yield this.getPixel(i, y); 43 | } 44 | } 45 | 46 | * getPixelsByCol(x) { 47 | const {width, height} = this; 48 | if(x < 0 || x >= width) return null; 49 | for(let j = 0; j < height; j++) { 50 | yield this.getPixel(x, j); 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /pixels/lib/math.js: -------------------------------------------------------------------------------- 1 | export function clamp(value, min, max) { 2 | if(min > max) [min, max] = [max, min]; 3 | if(value < min) return min; 4 | if(value > max) return max; 5 | return value; 6 | } 7 | 8 | export function mix(src, dest, p) { 9 | return src * (1 - p) + dest * p; 10 | } 11 | 12 | export function transformPoint(p, m) { 13 | const [x, y] = p; 14 | return [x * m[0] + y * m[2] + m[4], x * m[1] + y * m[3] + m[5]]; 15 | } -------------------------------------------------------------------------------- /polar-shader/circle.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 造型函数 7 | 8 | 9 | 10 | 11 | 69 | 70 | -------------------------------------------------------------------------------- /polar-shader/rose.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 造型函数 7 | 8 | 9 | 10 | 11 | 70 | 71 | -------------------------------------------------------------------------------- /polar-shader/rose2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 造型函数 7 | 8 | 9 | 10 | 11 | 76 | 77 | -------------------------------------------------------------------------------- /polygon-fill/app.js: -------------------------------------------------------------------------------- 1 | import {Vector2D} from '../common/lib/vector2d.js'; 2 | 3 | const canvas = document.querySelector('canvas'); 4 | const ctx = canvas.getContext('2d'); 5 | const {width, height} = canvas; 6 | const w = 0.5 * width, 7 | h = 0.5 * height; 8 | ctx.translate(w, h); 9 | ctx.scale(1, -1); 10 | 11 | function draw(context, points, { 12 | fillStyle = 'black', 13 | close = false, 14 | rule = 'nonzero', 15 | } = {}) { 16 | context.beginPath(); 17 | context.moveTo(...points[0]); 18 | for(let i = 1; i < points.length; i++) { 19 | context.lineTo(...points[i]); 20 | } 21 | if(close) context.closePath(); 22 | context.fillStyle = fillStyle; 23 | context.fill(rule); 24 | } 25 | 26 | const points = [new Vector2D(0, 100)]; 27 | for(let i = 1; i <= 4; i++) { 28 | const p = points[0].copy().rotate(i * Math.PI * 0.4); 29 | points.push(p); 30 | } 31 | 32 | const polygon = [ 33 | ...points, 34 | ]; 35 | 36 | ctx.save(); 37 | ctx.translate(-128, 0); 38 | draw(ctx, polygon); 39 | ctx.restore(); 40 | 41 | const stars = [ 42 | points[0], 43 | points[2], 44 | points[4], 45 | points[1], 46 | points[3], 47 | ]; 48 | 49 | ctx.save(); 50 | ctx.translate(128, 0); 51 | // draw(ctx, stars); 52 | draw(ctx, stars, {rule: 'evenodd'}); 53 | ctx.restore(); -------------------------------------------------------------------------------- /polygon-fill/fill-canvas2d.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Canvas2D填充 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /polyline-curve/canvas2d.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Polyline & curve 7 | 8 | 9 | 10 | 38 | 39 | -------------------------------------------------------------------------------- /polyline-curve/webgl-lines.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Lines 7 | 8 | 9 | 10 | 70 | 71 | -------------------------------------------------------------------------------- /qcharts/area.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 基础图形元素 7 | 20 | 21 | 22 |
23 | 24 | 25 | 57 | 58 | -------------------------------------------------------------------------------- /qcharts/bar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 基础图形元素 7 | 20 | 21 | 22 |
23 | 24 | 25 | 57 | 58 | -------------------------------------------------------------------------------- /qcharts/basic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 基础图形元素 7 | 20 | 21 | 22 |
23 | 24 | 25 | 51 | 52 | -------------------------------------------------------------------------------- /qcharts/gauge.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 基础图形元素 7 | 20 | 21 | 22 |
23 | 24 | 25 | 42 | 43 | -------------------------------------------------------------------------------- /qcharts/line.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 基础图形元素 7 | 20 | 21 | 22 |
23 | 24 | 25 | 57 | 58 | -------------------------------------------------------------------------------- /qcharts/pie.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 基础图形元素 7 | 20 | 21 | 22 |
23 | 24 | 25 | 54 | 55 | -------------------------------------------------------------------------------- /qcharts/radar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 基础图形元素 7 | 20 | 21 | 22 |
23 | 24 | 25 | 53 | 54 | -------------------------------------------------------------------------------- /qcharts/radial.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 基础图形元素 7 | 20 | 21 | 22 |
23 | 24 | 25 | 77 | 78 | -------------------------------------------------------------------------------- /repeat-and-random/random.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 重复网格 7 | 8 | 9 | 10 | 11 | 72 | 73 | -------------------------------------------------------------------------------- /shaping-functions/circle-repeat.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 造型函数 7 | 8 | 9 | 10 | 11 | 65 | 66 | -------------------------------------------------------------------------------- /shaping-functions/circle.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 造型函数 7 | 8 | 9 | 10 | 11 | 65 | 66 | -------------------------------------------------------------------------------- /shaping-functions/line-repeat.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 造型函数 7 | 8 | 9 | 10 | 11 | 67 | 68 | -------------------------------------------------------------------------------- /shaping-functions/line.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 造型函数 7 | 8 | 9 | 10 | 11 | 65 | 66 | -------------------------------------------------------------------------------- /sketch/index1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Sketch 8 | 9 | 10 | 62 | 63 | -------------------------------------------------------------------------------- /sketch/index2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Sketch 8 | 9 | 10 | 63 | 64 | -------------------------------------------------------------------------------- /sketch/index4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Sketch 8 | 9 | 10 | 59 | 60 | -------------------------------------------------------------------------------- /sketch/index5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Sketch 8 | 9 | 10 | 61 | 62 | -------------------------------------------------------------------------------- /sketch/index8.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Sketch 8 | 9 | 10 | 63 | 64 | -------------------------------------------------------------------------------- /sketch/lib/doodle.js: -------------------------------------------------------------------------------- 1 | const commandList = []; 2 | 3 | const position = [0, 0]; 4 | const direction = [1, 0]; 5 | 6 | function rotate(deg) { 7 | const rad = deg * Math.PI / 180, 8 | c = Math.cos(rad), 9 | s = Math.sin(rad); 10 | 11 | // [c, s, -s, c] 12 | 13 | const [x, y] = direction; 14 | 15 | direction[0] = x * c + y * -s; 16 | direction[1] = x * s + y * c; 17 | } 18 | 19 | export function pen(lineWidth, color = 'black') { 20 | commandList.push({ 21 | command: 'pen', 22 | args: {color, lineWidth}, 23 | }); 24 | put(...position); 25 | } 26 | 27 | export function put(x, y) { 28 | position[0] = x; 29 | position[1] = y; 30 | commandList.push({ 31 | command: 'put', 32 | args: {x, y}, 33 | }); 34 | } 35 | 36 | 37 | export function left(deg) { 38 | rotate(deg); 39 | } 40 | 41 | export function right(deg) { 42 | rotate(-deg); 43 | } 44 | 45 | export function forward(length) { 46 | position[0] += length * direction[0]; 47 | position[1] += length * direction[1]; 48 | 49 | commandList.push({ 50 | command: 'forward', 51 | args: { 52 | x: position[0], 53 | y: position[1], 54 | }, 55 | }); 56 | } 57 | 58 | export function render(parser) { 59 | parser([...commandList]); 60 | commandList.length = 0; 61 | } -------------------------------------------------------------------------------- /svg/basic/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Circle 7 | 8 | 9 | 10 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /svg/hierarchy/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Hierarchy render by canvas 7 | 14 | 15 | 16 |

17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /triangluations/polygon2d-collision.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 三角剖分 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /triangluations/polygon2d.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 三角剖分 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /triangluations/trianglu-polygon.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 三角剖分 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /vector_draw/app.js: -------------------------------------------------------------------------------- 1 | import {Vector2D} from '../common/lib/vector2d.js'; 2 | 3 | const canvas = document.querySelector('canvas'); 4 | const ctx = canvas.getContext('2d'); 5 | const {width, height} = canvas; 6 | ctx.translate(0.5 * width, 0.5 * height); 7 | ctx.scale(1, -1); 8 | 9 | function regularShape(edges = 3, x, y, step) { 10 | const ret = []; 11 | const delta = Math.PI * (1 - (edges - 2) / edges); 12 | let p = new Vector2D(x, y); 13 | const dir = new Vector2D(step, 0); 14 | ret.push(p); 15 | for(let i = 0; i < edges; i++) { 16 | p = p.copy().add(dir.rotate(delta)); 17 | ret.push(p); 18 | } 19 | return ret; 20 | } 21 | 22 | function draw(points, strokeStyle = 'black', fillStyle = null) { 23 | ctx.strokeStyle = strokeStyle; 24 | ctx.beginPath(); 25 | ctx.moveTo(...points[0]); 26 | for(let i = 1; i < points.length; i++) { 27 | ctx.lineTo(...points[i]); 28 | } 29 | ctx.closePath(); 30 | if(fillStyle) { 31 | ctx.fillStyle = fillStyle; 32 | ctx.fill(); 33 | } 34 | ctx.stroke(); 35 | } 36 | 37 | draw(regularShape(3, 128, 128, 100)); 38 | draw(regularShape(6, -64, 128, 50)); 39 | 40 | draw(regularShape(11, -64, -64, 30)); 41 | draw(regularShape(60, 128, -64, 6)); -------------------------------------------------------------------------------- /vector_draw/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 画正多边形 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /vector_tree/app.js: -------------------------------------------------------------------------------- 1 | import {Vector2D} from '../common/lib/vector2d.js'; 2 | 3 | const canvas = document.querySelector('canvas'); 4 | const ctx = canvas.getContext('2d'); 5 | 6 | ctx.translate(0, canvas.height); 7 | ctx.scale(1, -1); 8 | ctx.lineCap = 'round'; 9 | 10 | function drawBranch(context, v0, length, thickness, dir, bias) { 11 | const v = new Vector2D().rotate(dir).scale(length); 12 | const v1 = v0.copy().add(v); 13 | 14 | context.lineWidth = thickness; 15 | context.beginPath(); 16 | context.moveTo(...v0); 17 | context.lineTo(...v1); 18 | context.stroke(); 19 | 20 | if(thickness > 2) { 21 | const left = Math.PI / 4 + 0.5 * (dir + 0.2) + bias * (Math.random() - 0.5); 22 | drawBranch(context, v1, length * 0.9, thickness * 0.8, left, bias * 0.9); 23 | const right = Math.PI / 4 + 0.5 * (dir - 0.2) + bias * (Math.random() - 0.5); 24 | drawBranch(context, v1, length * 0.9, thickness * 0.8, right, bias * 0.9); 25 | } 26 | 27 | if(thickness < 5 && Math.random() < 0.3) { 28 | context.save(); 29 | context.strokeStyle = '#c72c35'; 30 | const th = Math.random() * 6 + 3; 31 | context.lineWidth = th; 32 | context.beginPath(); 33 | context.moveTo(...v1); 34 | context.lineTo(v1.x, v1.y - 2); 35 | context.stroke(); 36 | context.restore(); 37 | } 38 | } 39 | 40 | const v0 = new Vector2D(256, 0); 41 | drawBranch(ctx, v0, 50, 10, 1, 3); -------------------------------------------------------------------------------- /vector_tree/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 画树 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /vis-geo-earth/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/env", 5 | { 6 | "targets": { 7 | "chrome": 59 8 | }, 9 | "useBuiltIns": "usage", 10 | "corejs": 3 11 | } 12 | ] 13 | ] 14 | } -------------------------------------------------------------------------------- /vis-geo-earth/.demosrc.js: -------------------------------------------------------------------------------- 1 | export default { 2 | devServer: { 3 | port: 9090, 4 | }, 5 | output: { 6 | dir: 'docs', 7 | publicUrl: '.', 8 | html: { 9 | title: 'SpriteJS/next - The next generation of spritejs.' 10 | }, 11 | }, 12 | // themeFile: 'demos/theme.scss', 13 | staticFolder: 'dist', 14 | demoList: '.demoList.json', 15 | name: 'GLOBE', 16 | version: 'v1.0', 17 | homePage: 'https://git.corp.qihoo.net/qiwoo/vis-geo-earth', 18 | logo: '', 19 | // 可选主题: active4d, allHallowsEve, amy, blackboard, brillianceBlack, 20 | // brillianceDull, chromeDevtools, cloudsMidnight, clouds, cobalt, 21 | // dawn, dreamweaver, eiffel, espressoLibre, github, idle, katzenmilch, 22 | // kuroirTheme, lazy, magicwbAmiga, merbivoreSoft, merbivore, monokai, 23 | // pastelsOnDark, slushAndPoppies, solarizedDark, solarizedLight, 24 | // spacecadet, sunburst, textmateMacClassic, tomorrowNightBlue, 25 | // tomorrowNightBright, tomorrowNightEighties, tomorrowNight, tomorrow, 26 | // twilight, vibrantInk, zenburnesque, iplastic, idlefingers, krtheme, 27 | // monoindustrial, 28 | boxTheme: 'monokai', 29 | globalPackages: { 30 | js: ['./spritejs.js', './sprite-extend-3d.js', './sprite-geo-earth.js'], 31 | css: [], 32 | }, 33 | // tab waterfall 34 | editorViewMode: 'tab', 35 | editorOptions: { 36 | disableLayerHinting: true, 37 | } 38 | }; -------------------------------------------------------------------------------- /vis-geo-earth/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const packageConfig = require('./package.json'); 2 | 3 | module.exports = { 4 | env: { 5 | "browser": true, 6 | }, 7 | extends: 'eslint-config-sprite', 8 | plugins: ['html'], 9 | rules: { 10 | 'complexity': ['warn', 25], 11 | 'import/prefer-default-export': 'off', 12 | 'no-unused-vars': 'warn', 13 | }, 14 | } 15 | -------------------------------------------------------------------------------- /vis-geo-earth/demos/.demoList.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "label": "基础地球仪", 4 | "src": "basical" 5 | }, 6 | { 7 | "label": "光柱", 8 | "src": "beams" 9 | }, 10 | { 11 | "label": "标记", 12 | "src": "markers" 13 | }, 14 | { 15 | "label": "相机", 16 | "src": "camera" 17 | }, 18 | { 19 | "label": "曲线", 20 | "src": "curves" 21 | }, 22 | { 23 | "label": "地球纹理", 24 | "src": "globe" 25 | }, 26 | { 27 | "label": "飞线", 28 | "src": "missiles" 29 | }, 30 | { 31 | "label": "法线贴图", 32 | "src": "normalmap" 33 | } 34 | ] -------------------------------------------------------------------------------- /vis-geo-earth/demos/basical/config.js: -------------------------------------------------------------------------------- 1 | export default async () => { 2 | const [html, javascript, css] = await Promise.all([ 3 | import('!raw-loader!../index.html'), 4 | import('!raw-loader!./index.js'), 5 | import('!raw-loader!../style.css'), 6 | ]); 7 | 8 | return { 9 | javascript, 10 | html: { 11 | code: html, 12 | }, 13 | css: { 14 | code: css, 15 | }, 16 | packages: { 17 | js: [], 18 | }, 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /vis-geo-earth/demos/basical/index.js: -------------------------------------------------------------------------------- 1 | const {Scene} = spritejs; 2 | const container = document.getElementById('container'); 3 | const scene = new Scene({ 4 | container, 5 | }); 6 | const layer = scene.layer3d('fglayer', { 7 | alpha: false, 8 | camera: { 9 | fov: 35, 10 | }, 11 | }); 12 | layer.camera.attributes.pos = [0, 0, 3500 / Math.min(layer.width, layer.height)]; 13 | layer.camera.lookAt([0, 0, 0]); 14 | layer.gl.clearColor(0, 0, 0, 1); 15 | 16 | const {createGlobe} = spritejs.globe; 17 | 18 | // 创建地球 19 | const globe = createGlobe(layer, { 20 | program: null, // 这里有特殊需要可以传一个自定义的program进去,不过一般不需要 21 | data: spritejs.globe.config.topojsonData, // 数据源,默认是测试数据源,可以传任何topojson格式的世界地理数据覆盖它 22 | orbit: true, // 是否允许鼠标操作,默认为 true 23 | raycast: true, // 是否允许地球被点击,默认为 false 24 | highlight: true, // 是否让鼠标移动时高亮地区,这个需要同时将raycast设为true生效 25 | sky: true, // 是否显示星空,默认为true 26 | skyProgram: null, // 如果自定义背景天空,可以传一个program进去 27 | corona: true, // 是否显示地球背景的光晕,默认为true 28 | coronaProgram: null, // 如果自定义背景光晕,可以传一个program进去 29 | autoResize: true, // 是否在容器大小变化时自适应大小 30 | texture: null, // 是否加载地图纹理,默认不加载则用数据画 31 | tick() { // 可以在每一帧更新地球属性 32 | this.attributes.rotateY += 0.1; 33 | }, 34 | // ... 然后可以传其他的SpriteJS属性给元素 35 | rotateY: 150, 36 | }); -------------------------------------------------------------------------------- /vis-geo-earth/demos/beams/config.js: -------------------------------------------------------------------------------- 1 | export default async () => { 2 | const [html, javascript, css] = await Promise.all([ 3 | import('!raw-loader!../index.html'), 4 | import('!raw-loader!./index.js'), 5 | import('!raw-loader!../style.css'), 6 | ]); 7 | 8 | return { 9 | javascript, 10 | html: { 11 | code: html, 12 | }, 13 | css: { 14 | code: css, 15 | }, 16 | packages: { 17 | js: [], 18 | }, 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /vis-geo-earth/demos/beams/index.js: -------------------------------------------------------------------------------- 1 | const {Scene} = spritejs; 2 | const container = document.getElementById('container'); 3 | const scene = new Scene({ 4 | container, 5 | }); 6 | const layer = scene.layer3d('fglayer', { 7 | alpha: false, 8 | camera: { 9 | fov: 35, 10 | }, 11 | }); 12 | layer.camera.attributes.pos = [0, 0, 3500 / Math.min(layer.width, layer.height)]; 13 | layer.camera.lookAt([0, 0, 0]); 14 | layer.gl.clearColor(0, 0, 0, 1); 15 | 16 | const {createGlobe} = spritejs.globe; 17 | 18 | // 创建地球 19 | const globe = createGlobe(layer, { 20 | program: null, // 这里有特殊需要可以传一个自定义的program进去,不过一般不需要 21 | data: spritejs.globe.config.topojsonData, // 数据源,默认是测试数据源,可以传任何topojson格式的世界地理数据覆盖它 22 | orbit: true, // 是否允许鼠标操作,默认为 true 23 | raycast: true, // 是否允许地球被点击,默认为 false 24 | highlight: true, // 是否让鼠标移动时高亮地区,这个需要同时将raycast设为true生效 25 | sky: true, // 是否显示星空,默认为true 26 | skyProgram: null, // 如果自定义背景天空,可以传一个program进去 27 | corona: true, // 是否显示地球背景的光晕,默认为true 28 | coronaProgram: null, // 如果自定义背景光晕,可以传一个program进去 29 | autoResize: true, // 是否在容器大小变化时自适应大小 30 | texture: null, // 是否加载地图纹理,默认不加载则用数据画 31 | tick() { // 可以在每一帧更新地球属性 32 | this.attributes.rotateY += 0.1; 33 | }, 34 | // ... 然后可以传其他的SpriteJS属性给元素 35 | rotateY: 150, 36 | }); 37 | 38 | function randomPos() { 39 | return { 40 | latitude: -90 + 180 * Math.random(), 41 | longitude: -180 + 360 * Math.random(), 42 | }; 43 | } 44 | 45 | function randomColor() { 46 | return `hsl(${Math.floor(360 * Math.random())}, 100%, 50%)`; 47 | } 48 | 49 | const {addBeam} = spritejs.globe; 50 | 51 | for(let i = 0; i < 100; i++) { 52 | addBeam(globe, { 53 | ...randomPos(), 54 | color: randomColor(), 55 | segments: 3, 56 | }); 57 | } -------------------------------------------------------------------------------- /vis-geo-earth/demos/camera/config.js: -------------------------------------------------------------------------------- 1 | export default async () => { 2 | const [html, javascript, css] = await Promise.all([ 3 | import('!raw-loader!../index.html'), 4 | import('!raw-loader!./index.js'), 5 | import('!raw-loader!../style.css'), 6 | ]); 7 | 8 | return { 9 | javascript, 10 | html: { 11 | code: html, 12 | }, 13 | css: { 14 | code: css, 15 | }, 16 | packages: { 17 | js: [], 18 | }, 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /vis-geo-earth/demos/curves/config.js: -------------------------------------------------------------------------------- 1 | export default async () => { 2 | const [html, javascript, css] = await Promise.all([ 3 | import('!raw-loader!../index.html'), 4 | import('!raw-loader!./index.js'), 5 | import('!raw-loader!../style.css'), 6 | ]); 7 | 8 | return { 9 | javascript, 10 | html: { 11 | code: html, 12 | }, 13 | css: { 14 | code: css, 15 | }, 16 | packages: { 17 | js: [], 18 | }, 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /vis-geo-earth/demos/globe/config.js: -------------------------------------------------------------------------------- 1 | export default async () => { 2 | const [html, javascript, css] = await Promise.all([ 3 | import('!raw-loader!../index.html'), 4 | import('!raw-loader!./index.js'), 5 | import('!raw-loader!../style.css'), 6 | ]); 7 | 8 | return { 9 | javascript, 10 | html: { 11 | code: html, 12 | }, 13 | css: { 14 | code: css, 15 | }, 16 | packages: { 17 | js: [], 18 | }, 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /vis-geo-earth/demos/globe/index.js: -------------------------------------------------------------------------------- 1 | const {Scene} = spritejs; 2 | const container = document.getElementById('container'); 3 | const scene = new Scene({ 4 | container, 5 | }); 6 | const layer = scene.layer3d('fglayer', { 7 | alpha: false, 8 | camera: { 9 | fov: 35, 10 | }, 11 | }); 12 | layer.camera.attributes.pos = [0, 0, 3500 / Math.min(layer.width, layer.height)]; 13 | layer.camera.lookAt([0, 0, 0]); 14 | layer.gl.clearColor(0, 0, 0, 1); 15 | 16 | const {createGlobe, 17 | launchMissile, 18 | addMarker} = spritejs.globe; 19 | 20 | const texture = layer.createTexture('https://img.alicdn.com/tfs/TB1mR3bX3nH8KJjSspcXXb3QFXa-9000-4500.jpg'); 21 | 22 | const globe = createGlobe(layer, { 23 | orbit: true, 24 | raycast: true, 25 | rotateY: 310, 26 | texture, 27 | tick() { 28 | this.attributes.rotateY += 0.1; 29 | }, 30 | highlight: true, 31 | }); 32 | 33 | function randomColor() { 34 | const hue = Math.floor(Math.random() * 360); 35 | return `hsl(${hue}, 100%, 50%)`; 36 | } 37 | 38 | setInterval(() => { 39 | const from = { 40 | latitude: 90 - 180 * Math.random(), 41 | longitude: 180 - 360 * Math.random(), 42 | }; 43 | const to = { 44 | latitude: 90 - 180 * Math.random(), 45 | longitude: 180 - 360 * Math.random(), 46 | }; 47 | const color = randomColor(); 48 | const lifeTime = 1000; 49 | const height = 2.0; 50 | const width = 1.0; 51 | 52 | addMarker(globe, { 53 | ...from, 54 | lifeTime, 55 | height, 56 | color, 57 | width, 58 | // speed: 0.5, 59 | // segments: 4, 60 | }); 61 | 62 | setTimeout(() => { 63 | addMarker(globe, { 64 | ...to, 65 | lifeTime, 66 | height, 67 | color, 68 | width, 69 | // speed: 0.5, 70 | segments: 4, 71 | }); 72 | }, 0.5 * lifeTime); 73 | 74 | launchMissile(globe, { 75 | from, 76 | to, 77 | color, 78 | lifeTime, 79 | height, 80 | thickness: 0.75 * width, 81 | }); 82 | }, 100); 83 | -------------------------------------------------------------------------------- /vis-geo-earth/demos/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | SpriteJS 8 | 9 | 10 |
11 | 12 | -------------------------------------------------------------------------------- /vis-geo-earth/demos/markers/config.js: -------------------------------------------------------------------------------- 1 | export default async () => { 2 | const [html, javascript, css] = await Promise.all([ 3 | import('!raw-loader!../index.html'), 4 | import('!raw-loader!./index.js'), 5 | import('!raw-loader!../style.css'), 6 | ]); 7 | 8 | return { 9 | javascript, 10 | html: { 11 | code: html, 12 | }, 13 | css: { 14 | code: css, 15 | }, 16 | packages: { 17 | js: [], 18 | }, 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /vis-geo-earth/demos/markers/index.js: -------------------------------------------------------------------------------- 1 | const {Scene} = spritejs; 2 | const container = document.getElementById('container'); 3 | const scene = new Scene({ 4 | container, 5 | }); 6 | const layer = scene.layer3d('fglayer', { 7 | alpha: false, 8 | camera: { 9 | fov: 35, 10 | }, 11 | }); 12 | layer.camera.attributes.pos = [0, 0, 3500 / Math.min(layer.width, layer.height)]; 13 | layer.camera.lookAt([0, 0, 0]); 14 | layer.gl.clearColor(0, 0, 0, 1); 15 | 16 | const {createGlobe} = spritejs.globe; 17 | 18 | // 创建地球 19 | const globe = createGlobe(layer, { 20 | program: null, // 这里有特殊需要可以传一个自定义的program进去,不过一般不需要 21 | data: spritejs.globe.config.topojsonData, // 数据源,默认是测试数据源,可以传任何topojson格式的世界地理数据覆盖它 22 | orbit: true, // 是否允许鼠标操作,默认为 true 23 | raycast: true, // 是否允许地球被点击,默认为 false 24 | highlight: true, // 是否让鼠标移动时高亮地区,这个需要同时将raycast设为true生效 25 | sky: true, // 是否显示星空,默认为true 26 | skyProgram: null, // 如果自定义背景天空,可以传一个program进去 27 | corona: true, // 是否显示地球背景的光晕,默认为true 28 | coronaProgram: null, // 如果自定义背景光晕,可以传一个program进去 29 | autoResize: true, // 是否在容器大小变化时自适应大小 30 | texture: null, // 是否加载地图纹理,默认不加载则用数据画 31 | tick() { // 可以在每一帧更新地球属性 32 | this.attributes.rotateY += 0.1; 33 | }, 34 | // ... 然后可以传其他的SpriteJS属性给元素 35 | rotateY: 150, 36 | }); 37 | 38 | function randomPos() { 39 | return { 40 | latitude: -90 + 180 * Math.random(), 41 | longitude: -180 + 360 * Math.random(), 42 | }; 43 | } 44 | 45 | function randomColor() { 46 | return `hsl(${Math.floor(360 * Math.random())}, 100%, 50%)`; 47 | } 48 | 49 | function randomSegments() { 50 | return [3, 4, 5, 60][Math.floor(4 * Math.random())]; 51 | } 52 | 53 | const {addMarker} = spritejs.globe; 54 | 55 | for(let i = 0; i < 100; i++) { 56 | addMarker(globe, { 57 | ...randomPos(), 58 | color: randomColor(), 59 | segments: randomSegments(), 60 | height: 2.0, 61 | }); 62 | } -------------------------------------------------------------------------------- /vis-geo-earth/demos/missiles/config.js: -------------------------------------------------------------------------------- 1 | export default async () => { 2 | const [html, javascript, css] = await Promise.all([ 3 | import('!raw-loader!../index.html'), 4 | import('!raw-loader!./index.js'), 5 | import('!raw-loader!../style.css'), 6 | ]); 7 | 8 | return { 9 | javascript, 10 | html: { 11 | code: html, 12 | }, 13 | css: { 14 | code: css, 15 | }, 16 | packages: { 17 | js: [], 18 | }, 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /vis-geo-earth/demos/normalmap/config.js: -------------------------------------------------------------------------------- 1 | export default async () => { 2 | const [html, javascript, css] = await Promise.all([ 3 | import('!raw-loader!../index.html'), 4 | import('!raw-loader!./index.js'), 5 | import('!raw-loader!../style.css'), 6 | ]); 7 | 8 | return { 9 | javascript, 10 | html: { 11 | code: html, 12 | }, 13 | css: { 14 | code: css, 15 | }, 16 | packages: { 17 | js: [], 18 | }, 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /vis-geo-earth/demos/normalmap/index.js: -------------------------------------------------------------------------------- 1 | const {Scene} = spritejs; 2 | const container = document.getElementById('container'); 3 | const scene = new Scene({ 4 | container, 5 | }); 6 | const layer = scene.layer3d('fglayer', { 7 | alpha: false, 8 | pointLightColor: 'white', 9 | pointLightPosition: [3, 3, 6], 10 | camera: { 11 | fov: 35, 12 | }, 13 | }); 14 | layer.camera.attributes.pos = [0, 0, 3500 / Math.min(layer.width, layer.height)]; 15 | layer.camera.lookAt([0, 0, 0]); 16 | layer.gl.clearColor(0, 0, 0, 1); 17 | 18 | const {createGlobe} = spritejs.globe; 19 | 20 | const texture = layer.createTexture('https://p1.ssl.qhimg.com/t0134ac9718ebd1a04b.jpg'); 21 | const textureNormal = layer.createTexture('https://p1.ssl.qhimg.com/t01b29b04e3f0583969.jpg'); 22 | const bumpMap = layer.createTexture('https://p3.ssl.qhimg.com/t0124d7369806be89c6.jpg'); 23 | 24 | // 创建地球 25 | const globe = createGlobe(layer, { 26 | program: null, // 这里有特殊需要可以传一个自定义的program进去,不过一般不需要 27 | data: spritejs.globe.config.topojsonData, // 数据源,默认是测试数据源,可以传任何topojson格式的世界地理数据覆盖它 28 | orbit: true, // 是否允许鼠标操作,默认为 true 29 | raycast: true, // 是否允许地球被点击,默认为 false 30 | highlight: false, // 是否让鼠标移动时高亮地区,这个需要同时将raycast设为true生效 31 | sky: true, // 是否显示星空,默认为true 32 | skyProgram: null, // 如果自定义背景天空,可以传一个program进去 33 | corona: true, // 是否显示地球背景的光晕,默认为true 34 | coronaProgram: null, // 如果自定义背景光晕,可以传一个program进去 35 | autoResize: true, // 是否在容器大小变化时自适应大小 36 | texture, // 是否加载地图纹理,默认不加载则用数据画 37 | normalMap: textureNormal, // 法线纹理贴图 38 | bumpMap, // 凹凸纹理 39 | normalScale: 2, 40 | tick() { // 可以在每一帧更新地球属性 41 | this.attributes.rotateY += 0.1; 42 | }, 43 | // ... 然后可以传其他的SpriteJS属性给元素 44 | rotateY: 150, 45 | }); -------------------------------------------------------------------------------- /vis-geo-earth/demos/style.css: -------------------------------------------------------------------------------- 1 | html,body { 2 | margin: 0; 3 | padding: 0; 4 | background: #201e1e; 5 | height: 100%; 6 | width: 100%; 7 | max-width: 800px; 8 | overflow: hidden; 9 | } 10 | 11 | #container { 12 | display: inline-block; 13 | width: 100%; 14 | height: 0; 15 | padding-bottom: 100%; 16 | background: #201e1e; 17 | } -------------------------------------------------------------------------------- /vis-geo-earth/docs/assets/js/0.9783eddd.chunk.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[0],{136:function(t,e,n){"use strict";n.r(e),e.default='\n\n\n \n \n \n SpriteJS\n\n\n
\n\n'}}]); -------------------------------------------------------------------------------- /vis-geo-earth/docs/assets/js/1.a4a3b37a.chunk.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[1],{137:function(n,i,d){"use strict";d.r(i),i.default="html,body {\n margin: 0;\n padding: 0;\n background: #201e1e;\n height: 100%;\n width: 100%;\n max-width: 800px;\n overflow: hidden;\n}\n\n#container {\n display: inline-block;\n width: 100%;\n height: 0;\n padding-bottom: 100%;\n background: #201e1e;\n}"}}]); -------------------------------------------------------------------------------- /vis-geo-earth/docs/assets/js/13.56a12e9d.chunk.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[13],{431:function(t,r,e){"use strict";e.r(r),e.d(r,"conf",(function(){return s})),e.d(r,"language",(function(){return n}));var s={brackets:[],autoClosingPairs:[],surroundingPairs:[]},n={keywords:[],typeKeywords:[],tokenPostfix:".csp",operators:[],symbols:/[=>","<","<>","<=",">=","And","Or","+","-","*","/","="],identifier:/[a-zA-Z_][\w]*/,symbols:/[=><:+\-*\/%\.,]+/,escapes:/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[{include:"@whitespace"},[/(@identifier)(?=[.])/,"type"],[/@identifier/,{cases:{"@keywords":{token:"keyword.$0"},"@operators":"operator","@default":"variable.name"}}],[/([.])(@identifier)/,{cases:{$2:["delimiter","type.member"],"@default":""}}],[/\d*\.\d+/,"number.float"],[/\d+/,"number"],[/[()\[\]]/,"@brackets"],[/@symbols/,{cases:{"@operators":"operator","@default":"delimiter"}}],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"/,"string","@string"]],whitespace:[[/[ \t\r\n]+/,""],[/(\').*$/,"comment"]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"C?/,"string","@pop"]]}}}}]); -------------------------------------------------------------------------------- /vis-geo-earth/docs/assets/js/46.ccb35aec.chunk.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[46],{462:function(e,n,o){"use strict";o.r(n),o.d(n,"conf",(function(){return t})),o.d(n,"language",(function(){return s}));var t={comments:{lineComment:";",blockComment:["#|","|#"]},brackets:[["(",")"],["{","}"],["[","]"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'}]},s={defaultToken:"",ignoreCase:!0,tokenPostfix:".scheme",brackets:[{open:"(",close:")",token:"delimiter.parenthesis"},{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.square"}],keywords:["case","do","let","loop","if","else","when","cons","car","cdr","cond","lambda","lambda*","syntax-rules","format","set!","quote","eval","append","list","list?","member?","load"],constants:["#t","#f"],operators:["eq?","eqv?","equal?","and","or","not","null?"],tokenizer:{root:[[/#[xXoObB][0-9a-fA-F]+/,"number.hex"],[/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?/,"number.float"],[/(?:\b(?:(define|define-syntax|define-macro))\b)(\s+)((?:\w|\-|\!|\?)*)/,["keyword","white","variable"]],{include:"@whitespace"},{include:"@strings"},[/[a-zA-Z_#][a-zA-Z0-9_\-\?\!\*]*/,{cases:{"@keywords":"keyword","@constants":"constant","@operators":"operators","@default":"identifier"}}]],comment:[[/[^\|#]+/,"comment"],[/#\|/,"comment","@push"],[/\|#/,"comment","@pop"],[/[\|#]/,"comment"]],whitespace:[[/[ \t\r\n]+/,"white"],[/#\|/,"comment","@comment"],[/;.*$/,"comment"]],strings:[[/"$/,"string","@popall"],[/"(?=.)/,"string","@multiLineString"]],multiLineString:[[/[^\\"]+$/,"string","@popall"],[/[^\\"]+/,"string"],[/\\./,"string.escape"],[/"/,"string","@popall"],[/\\$/,"string"]]}}}}]); -------------------------------------------------------------------------------- /vis-geo-earth/docs/assets/js/52.f55e85d8.chunk.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /*!--------------------------------------------------------------------------------------------- 2 | * Copyright (C) David Owens II, owensd.io. All rights reserved. 3 | *--------------------------------------------------------------------------------------------*/ 4 | -------------------------------------------------------------------------------- /vis-geo-earth/docs/assets/js/56.babace81.chunk.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[56],{470:function(e,t,n){"use strict";n.r(t),n.d(t,"conf",(function(){return a})),n.d(t,"language",(function(){return o}));var a={comments:{blockComment:["\x3c!--","--\x3e"]},brackets:[["<",">"]],autoClosingPairs:[{open:"<",close:">"},{open:"'",close:"'"},{open:'"',close:'"'}],surroundingPairs:[{open:"<",close:">"},{open:"'",close:"'"},{open:'"',close:'"'}]},o={defaultToken:"",tokenPostfix:".xml",ignoreCase:!0,qualifiedName:/(?:[\w\.\-]+:)?[\w\.\-]+/,tokenizer:{root:[[/[^<&]+/,""],{include:"@whitespace"},[/(<)(@qualifiedName)/,[{token:"delimiter"},{token:"tag",next:"@tag"}]],[/(<\/)(@qualifiedName)(\s*)(>)/,[{token:"delimiter"},{token:"tag"},"",{token:"delimiter"}]],[/(<\?)(@qualifiedName)/,[{token:"delimiter"},{token:"metatag",next:"@tag"}]],[/(<\!)(@qualifiedName)/,[{token:"delimiter"},{token:"metatag",next:"@tag"}]],[/<\!\[CDATA\[/,{token:"delimiter.cdata",next:"@cdata"}],[/&\w+;/,"string.escape"]],cdata:[[/[^\]]+/,""],[/\]\]>/,{token:"delimiter.cdata",next:"@pop"}],[/\]/,""]],tag:[[/[ \t\r\n]+/,""],[/(@qualifiedName)(\s*=\s*)("[^"]*"|'[^']*')/,["attribute.name","","attribute.value"]],[/(@qualifiedName)(\s*=\s*)("[^">?\/]*|'[^'>?\/]*)(?=[\?\/]\>)/,["attribute.name","","attribute.value"]],[/(@qualifiedName)(\s*=\s*)("[^">]*|'[^'>]*)/,["attribute.name","","attribute.value"]],[/@qualifiedName/,"attribute.name"],[/\?>/,{token:"delimiter",next:"@pop"}],[/(\/)(>)/,[{token:"tag"},{token:"delimiter",next:"@pop"}]],[/>/,{token:"delimiter",next:"@pop"}]],whitespace:[[/[ \t\r\n]+/,""],[//,{token:"comment",next:"@pop"}],[/