npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

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

About

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

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

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

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

Open Software & Tools

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

© 2024 – Pkg Stats / Ryan Hefner

morthics

v0.2.4

Published

Mothics is a typescript framework designed to work with WebGL

Downloads

4

Readme

Morthics

Morthics is a typescript framework designed to work with WebGL. The framework is based on a component-based approach that makes development faster and easier. Morthics makes it possible to manage the program at a low level, and also ensures high speed of the program due to its simplicity, webgl and many optimizations

Installation

npm i morthics

Usage

main.ts

import { Application } from 'morthics'

;(async () => {
    const app = new Application(
        { resizeTo: window, backgroundColor: '#242424' },
        Main
    )

    await app.load

    document.body.appendChild(app.canvas)
})()

page.ts

import {
    Child,
    Component,
    Container,
    PageComponent,
    Preloads,
    Text,
} from 'morthics'
import styles from './page.style'

export class Main extends PageComponent {
    preLoad(): Preloads {
        {
            return {
                googleFonts: ['Snippet'],
            }
        }
    }

    render() {
        return Container({}, new HelloWorld())
    }
}

HelloWorld.ts

export class HelloWorld extends Component {

    render() {
        return Container(
            {},
            Text(styles.HelloWorld, 'Hello World!'),
        )
    }
}

page.style.ts

export default {
    HelloWorld: {
        style: {
            fill: '#ffffff',
            fontSize: 36,
            fontFamily: 'Snippet',
        },
    },
}

Documentation

Application

To create an application on Morthics, the first thing to do is create an object of the Application class

import { Application } from 'morthics'

const app = new Application(
    { resizeTo: window, backgroundColor: '#242424' },
    Main
)

In the constructor of the Application class, the first argument is passed to the object with the application settings, and the second argument is passed to PageComponent

Now we can add our application to the page, but before that we should make sure that the application has time to load and for this purpose the app object has a load field. Then all we need to do is to add the canvas to the desired part of the page.

import { Application } from 'morthics'

;(async () => {
    const app = new Application(
        { resizeTo: window, backgroundColor: '#242424' },
        Main
    )

    await app.load

    document.body.appendChild(app.canvas)
})()

PageComponent

PageComponent is a page component that is similar in its capabilities to a regular component. Like a Component, it has a render method that returns the markup for the whole page

import { PageComponent, Container, Text } from 'morthics'

export class Main extends PageComponent {
    render() {
        return Container(
            {},
            Text({}, 'Hello World!'),
        )
    }
}

preLoad

The preLoad method allows you to preload necessary data such as textures and fonts. To do this, return an object with the required fields from the preLoad method

It is also worth noting that fonts from google fonts and other fonts are downloaded differently in the array googleFonts should be passed to the names of fonts, and in the array fonts links to download them

export class Main extends PageComponent {
    preLoad(): Preloads {
        {
            return {
                googleFonts: ['Montserrat', 'Snippet'],
                textures: ['https://pixijs.com/assets/bunny.png'],
            }
        }
    }
    render() {
        return Container({}, new HelloWorld())
    }
}

Component

Сomponents in Morthics are created based on classes. Each component has its own life cycle and state. On different parts of the lifecycle you can hang event listeners, and the state can be changed, which will lead to the re-rendering of the component

This is an example of a simple counter, its logic can be simplified and not to create unnecessary components, but for a better understanding of working with components, props and state the button was placed in a separate component

page.ts

export class Main extends PageComponent {
    preLoad(): Preloads {
        {
            return {
                googleFonts: ['Montserrat', 'Snippet'],
                textures: ['https://pixijs.com/assets/bunny.png'],
            }
        }
    }
    render() {
        return Container({}, new HelloWorld())
    }
}

Hi.ts

export class Hi extends Component {
    beforeRender(): void {
        this.state.count = 0
        this.ref.Button = new CounterButton()
    }
    render() {
        const { Button } = this.ref

        return Container(
            { x: 10 },
            Text(
                {
                    style: {
                        fill: '#fff',
                    },
                },
                this.state.count
            ),
            withProps(Button, {
                count: this.state.count,
                increment: () => this.state.count++,
            })
        )
    }
}

CounterButton.ts

interface Props {
    count: number
    increment: () => void
}

export class CounterButton extends Component<Props> {
    render(): Child {
        const { count, increment } = this.props

        return Container(
            {},
            Button(
                {
                    onClick: increment,
                    y: 20,
                },
                count
            )
        )
    }
}

State

State is the data that tells you which component is which at any given moment. Any component except PageComponent has a state. It can be accessed via this.state and data can be written to it by normal assignment, but if you change the state, the component will be re-drawn

class CounterButton extends Component {
    beforeRender(): void {
        this.state.count = 0
    }
    render(): Child {
        return Container(
            {},
            Text(
                {
                    x: 130,
                    style: {
                        fill: '#fff',
                        fontFamily: 'Snippet',
                    },
                },
                this.state.count
            ),
            Container(
                { y: 50 },
                Button(
                    {
                        onClick: () => this.state.count++,
                    },
                    'increment'
                ),
                Button(
                    {
                        x: 75,
                        onClick: () => this.state.count--,
                    },
                    'decrement'
                )
            )
        )
    }
}

It is also important to realize that if you change several states in a row or change the same state many times, it does not mean that each assignment will be re-rendered, but only when necessary

this.state.count++
this.state.count++
this.state.y *= 2

// 1 re-render
this.state.count++
setTimeout(() => {
    this.state.count++
}, 1000)

// 2 re-renders
this.state.count = 0

setTimeout(() => {
    this.state.count = 0
}, 1000)

// 0 re-renders

Props

Through props you can pass data to the component from its parent for this you need to use the withProps function. If the props changes, the component will be redrawn. Props can be changed from a child, but then the re-rendering will not happen and unexpected behavior is possible, so it is better not to do this and if you really want to change its value, it is better to create a new variable

If necessary, a function can be passed to withProps as a third parameter to say whether the props have changed and depending on the answer the component will either be redrawn or not

export class Main extends PageComponent {
    render() {
        return Container(
            {},
            withProps(new YellowButton(), { text: 'button 1' }),
            withProps(
                new YellowButton(),
                {
                    text: 'button 2',
                    options: { x: 100, onClick: () => alert("It's button 2") },
                },
                (lastProps, newProps) => lastProps.text !== newProps.text
            )
        )
    }
}

YellowButton.ts

interface Props {
    text: string
    options?: ButtonOptions
}

export class YellowButton extends Component<Props> {
    render(): Child {
        const { text, options = {} } = this.props

        return Container(
            {},
            Button(
                {
                    bgColor: 0xffff00,
                    textStyle: {
                        fill: '#fff',
                    },
                    ...options,
                },
                text
            )
        )
    }
}

ref

Ref is the storage of this component. It performs the same functions as state, but with an important difference, which is that when ref is changed, the component is not re-rendered

Also, all the components you want to use should be written to ref (ref is absent in PageComponent, as it is not necessary to use it there)

class CounterButton extends Component {
    beforeRender(): void {
        this.ref.MyButton = new CounterButton()
        this.ref.text = 'Text'
    }
    render(): Child {
        const { MyButton, text } = this.ref

        return Container(
            {},
            MyButton(
                {},
                text,
            )
        )
    }
}

Sprite

Sprite is the analog of img in html it allows you to add images to a page

class Bunny extends Component {
    render(): Child {
        return Container(
            {},
            Sprite(
                { width: 50, height: 100 },
                'https://pixijs.com/assets/bunny.png'
            )
        )
    }
}

Container

Container allows you to group elements

class Bunnies extends Component {
    render(): Child {
        return Container(
            { x: 50 },
            Sprite(
                { width: 50, height: 100 }, // x == 50
                'https://pixijs.com/assets/bunny.png'
            ),
            Sprite(
                { x: 100, width: 50, height: 100 }, // x == 150
                'https://pixijs.com/assets/bunny.png'
            ),
        )
    }
}

Text (beta)

Text - allows you to write text on the page

export class HelloWorld extends Component {
    render() {
        return Container(
            {},
            Text(
                {
                    style: {
                        fill: '#ffffff',
                        fontSize: 36,
                        fontFamily: 'Snippet',
                    },
                },
                'Hello World!'
            )
        )
    }
}

Button (beta)

Button creates a button on the page. Initially it has a standard look similar to the browser button but it can be styled to your needs. You can place onClick, onHover, onUnHover event listeners on the button. You can also change border, button background, text styles, padding and more

class YellowButton extends Component<Props> {
    render(): Child {
        const { text, options = {} } = this.props

        return Container(
            {},
            Button(
                {
                    bgColor: 0xffff00,
                    textStyle: {
                        fill: '#fff',
                    },
                    ...options,
                },
                text
            )
        )
    }
}

animation (beta)

animation is a parameter that can be used with any standard component, it allows you to describe in a simple format the animation to be set for that component. You need to specify keyframes for certain percentages of animation execution

Parameters related to animation

  • animationTime: number // Animation execution time
  • animationType: 'default' | 'linear' // With linear animationType, animation occurs at the same speed at all stages and this is the fastest type of animation. In turn, with default animation animation is not at a constant speed (by default, the speed changes according to a sinusoidal graph)
  • animationFunction: [(x: number) => number, number,number] // animationFunction and function value area. animationFunction is a function that increments the speed of animation execution at a particular point in time. It is important that the function must be continuous over the specified definition area
  • startAnimation: boolean // by default it's true but if false then animation will not be applied
class MegaBunny extends Component {
    beforeRender(): void {
        this.state.y = 0
        this.state.count = 0
        this.state.startAnimation = false
    }
    jump() {
        this.state.startAnimation = true
        this.state.count++
    }
    render() {
        return Container(
            {
                x: (globalThis.innerWidth - 200) / 2,
                y: (globalThis.innerHeight - 400) / 2,
            },
            Sprite(
                {
                    width: 100,
                    height: 100,
                    animation: {
                        50: {
                            y: -150,
                        },
                        100: {
                            y: 0,
                        },
                    },
                    animationTime: 500,
                    animationType: 'default',
                    animationFunction: [(x) => Math.cos(x) + 1, 0, Math.PI],
                    startAnimation: this.state.startAnimation,
                },
                'https://pixijs.com/assets/bunny.png'
            ),
            Text(
                { style: { fill: 0xffffff }, y: 150, x: 40 },
                this.state.count
            ),
            Button(
                {
                    onClick: () => this.jump(),
                    borderSize: [0],
                    y: 100,
                    x: 5,
                    paddingLeft: 5,
                    paddingRight: 5,
                    borderRadius: 10,
                },
                'jump'
            )
        )
    }
}