Pen Settings



CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource


Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource


Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.


Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.






                // This is a remake of
// Coded by ScieCode in P5js - based on Hyper Glu's "Going to Quasar"

// ~~~~~~~~~~~~~~~~~~~~~~~~~~
// The roughly-equivilant ZIM version is 42% the size of the P5js code
// The approach was different - ScieCode's code is lovely and lower level
// With ZIM we can cheat a little... saving 58% and perhaps more readable?
// ~~~~~~~~~~~~~~~~~~~~~~~~~~

// ZIM is a JavaScript Canvas Framework for coding creativity!
// - please visit to start a wonderful coding journey.
// The main site has banner sections of TEN excellent uses of ZIM.

// ZIM provides many conveniences, components and controls 
// to help designers, developers and artists create interactive media 
// - why ZIM, features, applications
// - expand open any feature for info and examples

// Here are CodePen examples with comments for learning:
// - ZIM CodePen
// - ZIM Founder's CodePen

// There are also many tutorials, videos and references here:
// - ZIM Skool, ZIM Kids, ZIM Badges, etc.
// - ZIM Template, tools and more
// - come join us on Slack for discussion and support

// -----------------

// ZIM is powered by CreateJS so we import CreateJS and ZIM in CodePen settings
// We make a Frame object which makes a stage on an HTML canvas 
// We then add objects to the stage and update the stage to see them 
const scaling = "fit"; // this will resize to fit inside the screen dimensions
const width = 1024;
const height = 768;
const radius = 350;
const color = "#140c25";
const outerColor = "#140c25";

// we apply an alpha blendMode to the rings
// but do not want to apply the blendMode to the backing circle gradient
// so put the backing in a separate frame with its own canvas
const backing = new Frame(scaling, width, height, color, outerColor);
backing.on("ready", function() {
    var c = new Circle(radius).center().alp(.95);
    c.radialGradient([orange,"yellow","#1dada4","#140c35"],[0,.4,.7, 1], 0,0,0, 0,0,radius)
    backing.stage.update(); // to update the stage of the backing

const frame = new Frame(scaling, width, height);
frame.on("ready", function() {
    zog("ready from ZIM Frame"); // logs in console (F12 - choose console)

    let stage = frame.stage;
    let stageW = frame.width;
    let stageH = frame.height;

    // addTo(), center(), centerReg(), loc(), pos(), Ticker.add()
    // default to the stage of the first frame made
    // this will set the default stage to this frame
    zimDefaultFrame = frame;
    // frame.setDefault();

    const num = 4; // how many spinning shapes with rings
    const size = 3; // width of each ring
    const spacing = size*(num-1); // eg. four sets will each have three widths between rings

    // two vortexes are overlayed on each other
    // one has a blendmode that matches the color of a foil
    // the other applies white rings with a low alpha (.2)
    function vortex(num, alpha) {
        let r = radius+spacing*num*2; // with spacing, rings end up larger than radius - could fix, but like
        loop(num, k=>{
            let shape = new Shape(-r, -r, r*2, r*2).center().animate({
                props:{rotation:360*(k%2==0?1:-1)}, // spin oposite ways
            // make the number of rings and spacings to fit within radius
            loop(radius/(size+spacing), (i,t)=>{ // i is loop num, t is total loops
                // prepare for making arcs on rings
                // let there be 3-8 arcs and then a spacing for each
                let tot = rand(3,8)*2; // even
                // to divide these randomly, roll random numbers
                // then add them up and divide by total
                // apply the ratios to 360 degrees
                let divisors = [];
                loop(tot, j=>{divisors.push(rand());});
                let amount = divisors.reduce((a,b)=>a+b,0);
                divisors =>x/amount*360);
                // pic a random starting angle
                let start = rand(360);
                let last = start;
                // add arcs on ring at radius rr and angle last to last+next divisor angle
                // prefered the arcs to be generally longer than space between so multiplied by 1.5
                // could have divided the spacing arc by 1.5 but liked it better without doing that
                loop(divisors, (d,j)=>{
                    // tweak the arcs to not show white arcs at outer edges
                    // and not show blendmode arcs at inner edges
                    if ((num!=2 || (i<t-2)) && (num!=4 || (i>3))) {
                        // calculate radius of ring
                        let rr = spacing*k + i*(size+spacing);
                        if (j%2==0) { // alternate making arcs and leaving spaces
									 // want to make the white dots brighter so drop the opacity of arc
                            makeArc(shape, num==2?"rgba(255,255,255,.5)":white, rr, last, last+d*1.5);
                        } else {
                            // add a white dot roughly between the arcs
                            // at the angle and radius (cos and sin the angle for x and y)
                            // end stroke before starting and end fill afterwards
                            let angle = last+d/2;
                    last = last + d; // add the divisor to the last total (ring or no ring)
            shape.cache().alp(alpha); // cache the ring for performance and set alpha

    function makeArc(shape, color, radius, startAngle, endAngle) {, "round").a(0,0,radius,startAngle*Math.PI/180,endAngle*Math.PI/180);

    vortex(num, 1); // make a vortex with full alpha to get blendmode below

    // this will turn the white rings to the colors here
    // note, this gradient is slightly off the underneath backing
    // this makes the colors just a touch off
    var foil = new Circle(radius).center();
    foil.radialGradient([orange,"yellow","#1dada4","#140c35"],[.1,.3,.8,.9], 0,0,0, 0,0,radius)
    foil.blendMode = "source-in";

    vortex(num/2, .3); // make a vortex of white at an alpha of .2

    // add the planet and moon
    // to rotate a planet, set a large registration point and rotate
    const planet = new Circle(50).center().reg(-radius*.6).animate({
    planet.radialGradient(["#538a75","#19314d"],[0,.5], 35,0,85, 0,0,0)

    // set a large registration point of the moon container and add it to the planet
    // then rotate the moon container
    const moon = new Container(40,40).centerReg(planet).reg(planet.radius*2).animate({

    // create a moonBody for inside the moon container
    // we will later rotate the moon body to face the vortex (see Ticker)
    const moonBody = new Circle(20,null,yellow).center(moon);
    moonBody.radialGradient(["yellow",orange],[0,.5], 20,0,35, 0,0,0);

    // make the bright side of the moon face the center of the vortex
    // find the angle between the moonBody and the center of the vortex
    // to do this locate the point inside the coordinate space of the moon
    // that matches the center of the vortex which is at the center of the global stage
    // Use the moonBody x and y and the point to calculate the angle with the atan2
        let point = moon.globalToLocal(stageW/2, stageH/2);
        let angle = Math.atan2(moonBody.y-point.y, moonBody.x-point.x)*180/Math.PI
	// call remote script to make ZIM Foundation for Creative Coding icon and a greet link
	const greet = createGreet();
	timeout(3000, ()=>{


}); // end of ready