Flat, round, designer-friendly pseudo-3D engine for canvas & SVG

Overview

Zdog

Round, flat, designer-friendly pseudo-3D engine

View complete documentation and live demos at zzz.dog.

Install

Download

CDN

Link directly to Zdog JS on unpkg.

<script src="https://unpkg.com/zdog@1/dist/zdog.dist.min.js"></script>

Package managers

npm: npm install zdog

Bower: bower install zdog

Hello world demo

Create 3D models with Zdog by adding shapes. See Getting started for a walk-through of this demo.

let isSpinning = true;

let illo = new Zdog.Illustration({
  element: '.zdog-canvas',
  zoom: 4,
  dragRotate: true,
  // stop spinning when drag starts
  onDragStart: function() {
    isSpinning = false;
  },
});

// circle
new Zdog.Ellipse({
  addTo: illo,
  diameter: 20,
  translate: { z: 10 },
  stroke: 5,
  color: '#636',
});

// square
new Zdog.Rect({
  addTo: illo,
  width: 20,
  height: 20,
  translate: { z: -10 },
  stroke: 3,
  color: '#E62',
  fill: true,
});

function animate() {
  illo.rotate.y += isSpinning ? 0.03 : 0;
  illo.updateRenderGraph();
  requestAnimationFrame( animate );
}
animate();

About Zdog

Hi, Dave here. I wanted to make a video game. I needed a 3D engine, but most engines were too powerful and complex for me. I made Zdog so I could design and display simple 3D models without a lot of overhead.

Zdog is directly inspired by Dogz, a virtual pet game by P.F. Magic released in 1995. It used flat 2D circle sprites to render the Dogz’ models, but in a 3D scene. See Dogz playthrough video here. Dogz were fully animated in real time, running, flopping, scratching (on Windows 3.1!). It was remarkable.

Zdog uses the same principle. It renders all shapes using the 2D drawing APIs in either <canvas> or <svg>. Spheres are actually dots. Toruses are actually circles. Capsules are actually thick lines. It’s a simple, but effective trick. The underlying 3D math comes from Rotating 3D Shapes by Peter Collingridge.

Zdog is pronounced "Zee-dog" in American parlance or "Zed-dog" in British.

Beta!

Zdog v1 is a beta-release, of sorts. This is my first time creating a 3D engine, so I probably got some stuff wrong. Expect lots of changes for v2. Provide input and select new features on the Zdog issue tracker on GitHub.

More Zdog resources

Other people's stuff:

My stuff:


Licensed MIT. Made by Metafizzy 🌈 🐻

Comments
  • Animate items independently

    Animate items independently

    I have noticed that the only way to animate a shape rotation one full turn, is to animate the entire Illustration. The problem with this, is that every other item in the Illustration has to rotate. For instance, if I want to animate only the scale of a starfield, whilst animating only the full rotation of planets, there does not seem to be a way to achieve this, currently.

    How do I? 
    opened by charlesr1971 13
  • Jaggies showing on large canvas animation

    Jaggies showing on large canvas animation

    It maybe that ZDog is meant to be used for smaller animations and on the mobile. And I have noticed that all your demos are rendered on 240 width/height canvas. But, when you look at an animation on a desktop in Chrome with a canvas of 600 height etc, it is very easy to spot jagged edges when a shape is animated in rotation.

    http://hub.establishmindfulness.com/zdog

    opened by charlesr1971 10
  • Investigation into rotation issues in react-zdog

    Investigation into rotation issues in react-zdog

    @drcmda recommended in this comment that there's investigation in this repository to see why rotation might result in the issue I've found. To quote the linked issue:

    Creating the canvas with rotate already set results in a different rotation than changing the rotation after the initial render.

    Using Zdog alone, I've found this not to be the case, but @drcmda believes that the issue is down to a quirk in Zdog that neither of us fully understand yet.

    Sample of the issue: https://codesandbox.io/s/winter-sunset-csx9b

    opened by boardfish 9
  • construct complex shapes and import wavefront obj files

    construct complex shapes and import wavefront obj files

    Hi, This issue... is not really an issue ;) I created a github repository with some experiments I made with Zdog https://github.com/gregja/zdogXperiments In that repository, you'll find different techniques to create complex shapes in Zdog, and a function to import 3D objects (wavefront format). This function is largerly inspired by a similar function found in Phoria.js. I'll add other experiments later. I'm beginner with Zdog, so if you want to suggest me some improvements, don't hesitate ;) Thank's

    opened by gregja 7
  • dragRotate broken on mobile Chrome

    dragRotate broken on mobile Chrome

    So far with Zdog I've not had much luck with fluid dragRotate on anything other than desktop browser. If I try to drag on say Chrome on Android/iOS I can only drag a small amount before the drag stops. I've attached a GIF of the issue being replicated in the Chrome inspector.

    zdog drag issue

    Test case: https://codepen.io/desandro/pen/YbrLaO / zzz.dog

    I've taken a look through the code and think I have an idea of where to debug the issue. I'll see if I can put some time into it πŸ‘

    bug 
    opened by jh3y 7
  • How to make ZDog responsive?

    How to make ZDog responsive?

    I saw this Demo by Chris Gannon: https://codepen.io/chrisgannon/pen/PvVzRG The ZDog in this demo is responsive. I went through the code and I didn't found which part of code made it responsive... Can someone tell me which part of code make the demo responsive? Thank you!

    How do I? 
    opened by CHENXINNN 6
  • Add scale stroke option

    Add scale stroke option

    It would be great if we could have an option called for Group objects:

    ScaleStroke: true/false

    It is a little tedious having to alter the stroke value of each child object on top of scaling the parent object

    feature request 
    opened by charlesr1971 5
  • fix: Allow touch event when PointerEvent is not available

    fix: Allow touch event when PointerEvent is not available

    • The current implementation applies touch-action: none without checking for PointerEvent support.
    • Doing so means that if PointerEvent isn't available, ontouchstart will never fire. Effectively blocking the use of dragRotate with no error to the user.
    • This PR Adds a conditional where touch-action: none is being applied.
    • Also, in the case of downEvent === 'touchstart', use of preventDefault will throw log an error: Unable to preventDefault inside passive event listener due to target being treated as passive. You can read about this here: https://www.chromestatus.com/features/5093566007214080. Essentially event listeners aren't passive by default. But when it comes to touchstart and touchmove, they are in some browsers.
    • To avoid this, we can either wrap the event.preventDefault() call in a conditional based on the downEvent or explicitly set the event listener to passive: false. passive: false being the default in most cases and some browsers if the downEvent is touchstart/touchmove πŸ‘
    • To test the current version to see the issue, set window.PointerEvent = undefined; in a demo:
    <script>
      window.PointerEvent = undefined;
    </script>
    
    opened by jh3y 5
  • Unexpected Canvas Resize Behavior

    Unexpected Canvas Resize Behavior

    When setting resize: true on a canvas based illustration, it doesn't behave as I'd expect. For demos 1 and 2 below, I'd expect them to both have the same behavior. The SVG demo resizes proportionally, but the canvas demo stays locked at 480pxΓ—240px.

    Test Cases

    1. Canvas Resize: https://codepen.io/desandro/pen/pmdqZv 2. SVG Resize: https://codepen.io/desandro/pen/wbPREZ 3. Fullscreen Canvas Resize: https://codepen.io/desandro/pen/dEJxaV

    I realize that SVGs behave differently than canvases, since they retain their intrinsic proportions through their viewbox if explicit width/height is not defined, but that is not the case for canvas.

    I'm not sure what the solution is here. I went down a few roads, but then realized that there might be a few different behaviors that people are trying to achieve. Perhaps it's one, or a combination of the following (don't mind the horrible names):

    resize: false

    Zdog does not attempt to resize the illustration. Currently Working

    resize: 'fullscreen'

    Zdog will resize the illustration to match the viewport width and height. Currently Working, demo 3 above

    resize: 'fill-parent'

    Zdog will resize the illustration to match the width and height of the element's parent.

    resize: 'fill-parent-proportionally'

    Zdog will resize the illustration to match the smallest dimension of the element's parent, while proportionally scaling the opposite axis. This means the initial aspect ratio will be retained, but will try to fill its container. Think background-size: contain; from CSS.

    resize: 'respect-natural-dom-size-and-css'

    Zdog will resize the illustration based on the element's natural manifestation in the DOM, including any CSS applied. This would require Zdog to strip any explicit widths and heights from the element, take a natural measurement of the element in the DOM, then reapply those settings explicitly after the fact the keep the rendering working properly.


    There may be more options, and maybe I'm looking into this a little too closely, but I think resize solutions like this would cover most use cases. At a minimum, I'd expect resize: true to have some effect on the canvas, but that's not currently the case.

    Any suggestions or guidance here?

    P.S. - I'm loving Zdog, Dave, well done!

    bug 
    opened by jackrugile 5
  • Interop instead of baked-in animations & gestures

    Interop instead of baked-in animations & gestures

    Referencing this: https://github.com/metafizzy/zdog/issues/28#issuecomment-497478694

    It makes the lib larger, creates complexity, puts a fork into adoption. If this would be a small, focussed project it would benefit from existing eco systems, as well as creating one for its own.

    3rd-party use-cases could be documented, i've already seen people use GSAP with it for instance. For gestures especially low level access pointers per element (click, over, out, up, down, etc) are more interesting that high-level abstracts (onDrag).

    opened by drcmda 5
  • Use a build tool to reduce boilerplate code in js/* files and to make final builds smaller

    Use a build tool to reduce boilerplate code in js/* files and to make final builds smaller

    Hey there, so i noticed a couple fo the bugs that have been logged so far are for the most part just issues with missing modules being imported from other files or other similar build related issues.

    I was wondering if you would be open to someone contributing a PR that would update the build task to use a tool like rollup to generate all the boilerplate code required thus making the src files a bit easier to read and hopefully less susceptible to small build related bugs sneaking in.

    It would also give you out of the box esm builds for modern systems that support import syntax as well as umd builds and cjs builds. I would hope it would relieve some of the burden of these small bugs to give you more chances to work on some more cool features.

    I would love to hear your thoughts on this, if you would like to see what the code change would look like I maaaayy have already started the work so let me know.

    Thanks

    opened by sammdec 5
  • Better documentation of normalizeRotate()

    Better documentation of normalizeRotate()

    How would I implement object.normalizeRotate()? do I just shove it in the lines of x,y,z rotations? I tried just pasting it as line 32. I tried checking if there were any codepen.io or jsfiddle or examples on the zdog site that would use normalizeRotate but no such luck.

    https://codepen.io/dinkbat/pen/abYmYBg

    I put it on line 32 as illo.normalizeRotate(TAU/8); after defining the const TAU. This does not seem to affect the rotation at all.

    My goal is to always have 3 sides of the cube visible as it rotates, as one side starts to disappear, it'll start rotating the other way.

    Also thank you for this library its fantastic! I just wish I could use it a bit better.

    opened by brenly 0
  • Stroke Dasharray [feature request]

    Stroke Dasharray [feature request]

    Love the library! I was messing around with it for several hours last night. I tried to add the ability to enable the stroke-dasharray element on the path but I got bogged down.

    Would this be something you would think of adding in the future or is there more complexity to this than I imagine?

    feature request 
    opened by pistell 0
  • camera move(feature request)

    camera move(feature request)

    Can you add a way to manage a camera?

    I try to add a way to move the main anchor to simulate it, but rotating the main anchor is not the same as rotating yourcamera

    opened by sarahBuisson 2
  • using for-loop and variables in path command

    using for-loop and variables in path command

    In other languages, if I wanted to draw a star, say, I'd have something like this:

    startShape();
    for (i = 0;  i < numPoints; i++)
    {
      angleR = TAU/numPoints * i;
      angler = TAU/numPoints * (i + 0.5);
    
      vertex(bigRadius * cos(angleR), bigRadius * sin(angleR));
      vertex(smallRadius * cos(angler), smallRadius * sin(angler));
    }
    endShape();
    

    Can I do something similar in zdog? If so, I can't work out how, nor can I work out how to pass a variable to the path command.

    var x1 = Math.random(-50, 50);
    var y1 = Math.random(-50, 50);
    var z1 = Math.random(-50, 50);
    var x2 = Math.random(-50, 50);
    var y2 = Math.random(-50, 50);
    var z2 = Math.random(-50, 50);
    
    new Zdog.Shape({
      ...
      path: [
        { x: x1, y: y1, z: z1 }, 
        { x: x2, y: y2, z: z2 }, 
      ],
      ...
    

    Have I got the syntax wrong or am I hoping for too much? Thanks!

    opened by allonestring 1
  • how animate a shape with a path

    how animate a shape with a path

    I draw a line with Shape, I want to change it with the time, how do I do?

    I've try:

    let s=new Zdog.Shape({ addTo: illo, path: [ // triangle { x: 0, y: -40 }, { x: 40, y: 40 }, { x: -40, y: 40 }, ], closed: false, // unclosed stroke: 20, color: '#636' }); s.path= [ // triangle { x: 0, y: -90 }, { x: 10, y: 40 }, { x: -40, y: 40 }, ]

    but it seems that the new value of path is not updated :(

    opened by sarahBuisson 1
Releases(v1.1.1)
  • v1.1.1(Oct 23, 2019)

    🐞 check for browser window to address server-side bug #49 #85 #86 πŸ“¦ Add unpkg field to package.json #83 πŸ“¦ update deps: eslint & uglify-js πŸ— Remove Makefile in favor of npm scripts

    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Jun 14, 2019)

    🐞 #44 fix SVG rendering, remove checkFlatGraph 🐞 #53 fix chrome touch dragging 🐞 #65 add Box face property setter 🐞 #57 remove .includes for IE11 🐞 #26 More accurate Z sorting of Shapes πŸ”” New feature: Vector.isSame. Not a big upgrade, but technically it counts as a minor semver upgrage

    Source code(tar.gz)
    Source code(zip)
  • v1.0.2(Jun 4, 2019)

    🐞 #10 - Fix index.js exports. Export Zdog classes 🐞 #10 - Fix missing renderer dependencies 🐞 #21 - Fix adding/removing shapes to graph. Refactor checking flatGraph πŸ‘• #18 #30 - Switch to eslint 🐞 #41 - Fix resize bug for high pixel ratio

    Source code(tar.gz)
    Source code(zip)
  • v1.0.1(Jun 4, 2019)

    πŸ›  change to Cylinder.frontFace 🐞 fix centering for hi-res displays πŸ“ revise .github, readme, comments πŸ“¦ add npm version task

    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(Jun 4, 2019)

    Launch with CanvasRenderer, SvgRenderer, Vector, Anchor, Dragger, Illustration, PathCommand, Shape, Group, Rect, RoundedRect, Ellipse, Polygon, Hemisphere, Cylinder, Cone, and Box.

    Source code(tar.gz)
    Source code(zip)
Owner
Metafizzy
Delightful JS plugins
Metafizzy
Javascript Canvas Library, SVG-to-Canvas (& canvas-to-SVG) Parser

Fabric.js Fabric.js is a framework that makes it easy to work with HTML5 canvas element. It is an interactive object model on top of canvas element. I

Fabric.js 23.6k Jan 3, 2023
HTML5 Canvas Gauge. Tiny implementation of highly configurable gauge using pure JavaScript and HTML5 canvas. No dependencies. Suitable for IoT devices because of minimum code base.

HTML Canvas Gauges v2.1 Installation Documentation Add-Ons Special Thanks License This is tiny implementation of highly configurable gauge using pure

Mykhailo Stadnyk 1.5k Dec 30, 2022
Konva.js is an HTML5 Canvas JavaScript framework that extends the 2d context by enabling canvas interactivity for desktop and mobile applications.

Konva Konva is an HTML5 Canvas JavaScript framework that enables high performance animations, transitions, node nesting, layering, filtering, caching,

konva 8.7k Jan 8, 2023
React + Canvas = Love. JavaScript library for drawing complex canvas graphics using React.

React Konva React Konva is a JavaScript library for drawing complex canvas graphics using React. It provides declarative and reactive bindings to the

konva 4.9k Jan 9, 2023
Canvas rendering library, Sprite manipulation of canvas

el-canvas Canvas rendering library, Sprite manipulation of canvas hello world <div id="app"><div></div></div> yarn add elem-canvas or npm i

null 15 Apr 13, 2022
Bring data to life with SVG, Canvas and HTML. :bar_chart::chart_with_upwards_trend::tada:

D3: Data-Driven Documents D3 (or D3.js) is a JavaScript library for visualizing data using web standards. D3 helps you bring data to life using SVG, C

D3 103.8k Jan 3, 2023
πŸ“Έ Generate image using HTML5 canvas and SVG

egami β†’ image README | δΈ­ζ–‡ζ–‡ζ‘£ Generate image using HTML5 canvas and SVG Fork from html-to-image Installation pnpm pnpm add egami npm npm i egami Usage i

weng 12 Jan 3, 2023
JavaScript SVG parser and renderer on Canvas

canvg JavaScript SVG parser and renderer on Canvas. It takes the URL to the SVG file or the text of the SVG file, parses it in JavaScript and renders

null 3.3k Jan 4, 2023
Demonstration of liquid effect on HTML Canvas using Matter.js and SVG Filters (Blur + Contrast)

Canvas Liquid Effect Demonstration of liquid (or gooey) effect on HTML Canvas using Matter.js and SVG Filters (feGaussianBlur and feColorMatrix). DEMO

Utkarsh Verma 78 Dec 24, 2022
Babylon.js is a powerful, beautiful, simple, and open game and rendering engine packed into a friendly JavaScript framework.

Babylon.js Getting started? Play directly with the Babylon.js API using our playground. It also contains a lot of samples to learn how to use it. Any

Babylon.js 19.1k Jan 4, 2023
A friendly reusable charts DSL for D3

D4 D4 is a friendly charting DSL for D3. The goal of D4 is to allow developers to quickly build data-driven charts with little knowledge of the intern

Mark Daggett 429 Dec 5, 2022
The friendly, pragmatic and functional ID system

pika Combine Stripe IDs with Snowflake IDs and you get... pika! - the last ID system you'll ever need, combining pragmatism with functionality. Exampl

Hop 89 Jan 3, 2023
Simple HTML5 Charts using the tag

Simple yet flexible JavaScript charting for designers & developers Documentation Currently, there are two versions of the library (2.9.4 and 3.x.x). V

Chart.js 59.4k Jan 7, 2023
The Swiss Army Knife of Vector Graphics Scripting – Scriptographer ported to JavaScript and the browser, using HTML5 Canvas. Created by @lehni & @puckey

Paper.js - The Swiss Army Knife of Vector Graphics Scripting If you want to work with Paper.js, simply download the latest "stable" version from http:

Paper.js 13.5k Dec 30, 2022
πŸ”₯ JavaScript Library for HTML5 canvas based heatmaps

heatmap.js Dynamic Heatmaps for the Web. How to get started The fastest way to get started is to install heatmap.js with bower. Just run the following

Patrick Wied 5.9k Jan 2, 2023
Financial lightweight charts built with HTML5 canvas

Lightweight Charts Demos | Documentation | Discord community TradingView Lightweight Charts are one of the smallest and fastest financial HTML5 charts

TradingView, Inc. 5.8k Jan 9, 2023
Interactive visualizations of time series using JavaScript and the HTML canvas tag

dygraphs JavaScript charting library The dygraphs JavaScript library produces interactive, zoomable charts of time series: Learn more about it at dygr

Dan Vanderkam 3k Jan 3, 2023
🍞🎨 Full-featured photo image editor using canvas. It is really easy, and it comes with great filters.

Full featured image editor using HTML5 Canvas. It's easy to use and provides powerful filters. Packages toast-ui.image-editor - Plain JavaScript compo

NHN 5.7k Jan 6, 2023
πŸ¦β€’ [Work in Progress] React Renderer to build UI interfaces using canvas/WebGL

React Ape React Ape is a react renderer to build UI interfaces using canvas/WebGL. React Ape was built to be an optional React-TV renderer. It's mainl

Raphael Amorim 1.5k Jan 4, 2023