Git Product home page Git Product logo

tick's Introduction

Tick Counter

A ticker for declaritive building of countdowns and counters.

Supports:

  • Counting towards a date
  • Counting up from a date
  • Scheduling multiple intervals
  • Polling a value from a server
  • Presenting a simple value

Some examples:

You can also use Tick to create Flip counters

Made with ❤ By Rik Schennink

Docs

Information on how to customize Tick and use the Tick API can be found on the product website.

See index below:

Install from NPM

npm i @pqina/tick --save
import Tick from '@pqina/tick';

console.log(Tick);
// logs {supported: true, options: {…}, helper: {…}, data: {…}, DOM: {…}, …}

Quick Introduction

Building Tick Counters is very similar to building with Legos. Open the example implementation, clear the existing example, and follow along.

Start with the base .tick block:

<div class="tick">

</div>

We haven't yet entered a value so we won't see anything on the screen.

Let's do that now, add a value using the data-value attribute.

<div class="tick"
     data-value="50">

</div>

Tick now automatically adds a plain "text" view to present our value.

We can also present strings instead of numbers.

<div class="tick"
     data-value="Hello World">

</div

This is useful but not very spectacular, let's do something more interesting. We'll switch back to numbers and setup a "line" progress counter.

We tell Tick to render a different view by adding an HTML element with a data-view attribute. In this case the line view.

<div class="tick"
     data-value="50">

    <span data-view="line"></span>

</div>

It does not show the set progress. Maybe it's because there's no room to render our line view. We'll replace the span element with a div to make it stretch the entire width of the demo area.

<div class="tick"
     data-value="50">

    <div data-view="line"></div>

</div>

That wasn't it.

We don't see anything because line doesn't know its maximum value and therefor cannot determine what progress to show. We have to feed line a a value between 0 and 1, where 0 is empty and 1 is full.

We can do this by telling it the maximum value. We'll add a transform that calculates the value between 0 and 1 for a value in a certain range (in this case 0 and 100).

<div class="tick"
     data-value="50">

    <div data-view="line" data-transform="fraction(0,100)"></div>

</div>

There we go! We put in a value of 50 and the fraction transform turns it into 0.5

Let's update our counter each second so we can see the progress bar fill up. Bind a function to the data-did-init callback. We'll limit its value to a 100.

We'll also add a nice animation using the spring transform. See how we can pipe values from one transform to the other.

<div class="tick"
     data-value="50"
     data-did-init="handleTickInit">

    <div data-view="line" data-transform="fraction(0,100) -> spring"></div>

</div>
<script>
function handleTickInit(tick) {

    // The Tick `interval` function is an easy way to quickly setup a timer
    Tick.helper.interval(function() {

        // We simply increase the value of our ticker each second
        if (tick.value < 100) {
            tick.value += 5;
        }
        else {
            tick.value = 0;
        }

    });

}
</script>

There you have it, a simple progress bar build with Tick.

Read the documentation to take a deep dive into what's possible with Tick.

License

MIT License, Enjoy!

tick's People

Contributors

rikschennink avatar ryno1234 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

tick's Issues

Publish on NPM

Also, is there any difference between tick & flip?

From what I can tell tick seems more lower level than flip.

dangling requestAnimationFrame loop causes high CPU usage, even after it is destroyed

Hello and congratulations for this nice and sophisticated library!

I'm using a simple flip countdown (using one of the examples from pqina/flip). The countdown is created and destroyed dynamically. However after being destroyed (which is done with tickInstance.destroy()) I noticed an unusual high CPU usage.

After some investigation I found the problem: in the presentTick function in https://github.com/pqina/tick/blob/master/src/core/js/utils.js, draw is called recursively using requestAnimationFrame. This loop doesn't stop, even after the tick instance is destroyed.

I solved the problem with a quick and dirty monkey-patch:

  1. after calling tickInstance.destroy(), set tickInstance._IS_DESTROYED = true;
  2. in presentTick, check if the instance is destroyed before calling requestAnimationFrame, that is:
	var draw = function draw() {
		instance.baseDefinition.presenter.draw();

		if (instance._IS_DESTROYED) { return; }

		requestAnimationFrame(draw);
	};

The CPU is now back to 0 as expected, so I'm pretty sure the problem was here.

Hopefully this problem can be solved in a future release.

Thanks for your time.

Transitions cannot be changed

I am trying to change the transition on one of the code examples provided in the docs. However; the transition for changing values is always the crossfade transition when I view the output in the browser.

This is the markup I am using:

<script src="js/tick.view.swap.global.min.js"></script>
<script src="js/tick.core.kickstart.min.js"></script>
<div class="tick"
     data-value="1234"
     data-style="transition-in:
        scale(.8, 1) .75s ease-out-bounce .5s,
        fade(0, 1) .25s .5s;

      transition-out:
        fade(1, 0) .5s"
     data-did-init="setupFlip">
    <div data-repeat="true">
        <span data-view="swap"></span>
    </div>
</div>

<script>
	function setupFlip(tick) {
		Tick.helper.interval(function() {
			tick.value++;
		}, 1000);
	}
</script>

Uncaught TypeError: Cannot read property 'root' of null

Hi, I'm creating a shortcode for WordPress and element for Avada fusion builder and the output and script is working properly on frontend but not no backend editor, here's the screenshot my code on backend builder.

The issue is to create a Tick counter on the element selected with the given selector.

/* global FusionPageBuilderApp */
var FusionPageBuilder = FusionPageBuilder || {};

( function () {
jQuery( document ).ready( function () {
FusionPageBuilder[ better_script_vars_flip.shortcode_name ] = FusionPageBuilder.ElementView.extend( {

		/**
		 * Runs after view DOM is patched.
		 *
		 * @since 2.0
		 * @return {void}
		 */
		onRender: function () {
			var self = this;

			jQuery( window ).on( 'load', function() {
				self.afterPatch();
			} );
		},

		/**
		 * Runs after view DOM is patched.
		 *
		 * @since 2.0
		 * @return {void}
		 */
		afterPatch: function () {
			this._refreshJs();

			var element = jQuery( '#fb-preview' )[ 0 ].contentWindow.jQuery( this.$el.find( '.tick' ) );

			var counter,
				dateTime = this.model.attributes.params.datetime || new Date(),
				schedule = this.model.attributes.params.schedule || '',
				flipType = this.model.attributes.params.type,
				dateTimeFormat = this.model.attributes.params.format,
				format = {
					format: 'string' === typeof dateTimeFormat ? dateTimeFormat.split(',') : [],
				};

			if ( 0 < element.length ) {

				// setTimeout( function() {

					// if ( 'undefined' !== element ) {

						var tick = element.tick( 'create' );
		
						if ( 'count_down' === flipType ) {
							counter = jQuery.tick.count.down( dateTime, format );
						} else if ( 'count_up' === flipType ) {
							const dateOnly =
								"string" === typeof dateTime
									? dateTime.split(/[ T]+/)[0]
									: new Date() + 1;
							counter = jQuery.tick.count.up( dateOnly, format );
						} else if ( 'schedule' === flipType ) {
							counter = jQuery.tick.count.schedule( schedule, format );
						} else {
							jQuery.tick.helper.interval( function() {
								var d = jQuery.tick.helper.date();
								tick.tick( 'value', {
									sep: ':',
									hours: d.getHours(),
									minutes: d.getMinutes(),
									seconds: d.getSeconds()
								} );
							} );
						}
		
						if ( 'clock' !== flipType ) {
							counter.onupdate = function ( value ) {
								tick.tick( 'value', value );
							};
						}

					// }

				// }, 100 );

			}
		},
	} );
} );

} )( jQuery );

Screenshot 2020-10-21 101114

`format` in `Tick.count.down` gives error when including `Y` & `M`

I'm playing around with tick so I cloned this repo.

Created a duplicate of example/index.html, named it example/index2.html & here's my HTML:

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width" />
		<title>Tick Example Preset</title>

		<link rel="stylesheet" href="../dist/core/tick.core.min.css" />
		<link rel="stylesheet" href="../dist/view-swap/tick.view.swap.min.css" />
	</head>
	<body>
		<style>
			.tick {
				font-size: 2rem;
			}
		</style>

		<p>Countdown from a date - How many days till 2021?</p>
		<div class="tick" data-did-init="startDateCountdown">
			<span data-view="text"></span>
		</div>

		<script>
			function startDateCountdown(tick) {
				var counter = Tick.count.down('2021', {
					format: ['Y', 'M', 'd', 'h', 'm', 's'],
				})
				counter.onupdate = function (value) {
					tick.value = value
				}
				counter.onended = function () {}
			}
		</script>

		<!-- END OF TICK EXAMPLE PRESET -->

		<script src="../dist/view-swap/tick.view.swap.global.min.js"></script>
		<script src="../dist/core/tick.core.kickstart.min.js"></script>
	</body>
</html>

The relevant parts:

<p>Countdown from a date - How many days till 2021?</p>
<div class="tick" data-did-init="startDateCountdown">
	<span data-view="text"></span>
</div>

<script>
	function startDateCountdown(tick) {
		var counter = Tick.count.down('2021', {
			format: ['Y', 'M', 'd', 'h', 'm', 's'],
		})
		counter.onupdate = function (value) {
			tick.value = value
		}
		counter.onended = function () {}
	}
</script>

This should work as expected but displays the following instead:

tick

If I remove Y & M from format, it works. If I make the year 3021, it still throws error.

How to get extension "dots"... Error: Can't get extension with name "dots", "dots" is not available

I could create a Flip timer using

import Tick from 'https://cdn.jsdelivr.net/npm/@pqina/[email protected]/+esm';
...
Tick.DOM.create({
  value: 1,
  view: {
    ....
  }
})

But not sure how to create a dots counter. I tried the following way:

import Tick from 'https://cdn.jsdelivr.net/npm/@pqina/[email protected]/+esm';
...
Tick.DOM.create({
  value: {
    days: 12,
  },
  view: {
    children: [
      {
        root: 'div',
        children: [
          {
            view: 'dots',
            key: 'days',
          },
        ],
      },
    ],
  },
});

The web console says
image

If I had to do it using this way Tick.DOM.create with value and view params.... how would I be able to render a dots timer?

I can't find any import with +esm that includes core and dots.

Resizing the browser causes counter to start infinitely

I had a counter that initialized at 0, when I resize the browser or a user on iPhone scrolls left/right slightly the counter starts to count infinitely.

No errors in console on why this happens..

Here is my component:
`
import React, { useRef, useEffect } from "react";
import Tick from "@pqina/flip";
import "@pqina/flip/dist/flip.min.css";
import './index.css';

export const Flipr = ({ value }) => {
const divRef = useRef();
const tickRef = useRef();

useEffect(() => {
    const currDiv = divRef.current;

    Tick.DOM.create(currDiv, {
        value,
        didInit: (tick) => {
            tickRef.current = tick;
        },
        view: {
            children: [
                {
                    repeat: true,
                    root: "div",
                    style: ".flip",
                    transform: "step(1) -> arrive -> step(1)",
                    transition: "crossfade",
                    view: '',
                    children: [
                        {
                            view: "flip"
                        }
                    ]
                }
            ]
        }
    });

    return () => Tick.DOM.destroy(tickRef.current);
}, [value]);

useEffect(() => {
    if (tickRef.current) {
        tickRef.current.value = value;
    }
}, []);

return (
    <div>
        <div ref={divRef} />
    </div>
)

};
`

App.js:

<Flipr value={0} />

package.json -- "@pqina/flip": "1.7.5",

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.