Code Monkey home page Code Monkey logo

sakana-widget's Introduction

🐟「Sakana! Widget」

English | 简体中文

NPM License Codacy jsDelivr Upstream Rate this package

https://github.dsrkafuu.net/sakana-widget/

Add the Sakana! Widget to your own web page! Support custom images, auto resizing and more runtime params!

Features

  • Register and use your own character
  • Auto resizing support, 120px minimum
  • Press and hold the stand and drag, after releasing the hand the stand will bounce in the opposite direction
  • Use control bar to switch roles and use other functions
  • Automatic mode, applying a force of random size at random intervals
  • Prepared for CDN/NPM import, custom parameters, chained calls

Usage

First you need to import the module, either directly using a CDN or by installing it as an NPM package:

<!-- https://cdn.jsdelivr.net/npm/[email protected]/lib/sakana.min.css -->
<!-- https://cdn.jsdelivr.net/npm/[email protected]/lib/sakana.min.js -->
<!-- https://cdnjs.cloudflare.com/ajax/libs/sakana-widget/2.7.0/sakana.min.css -->
<!-- https://cdnjs.cloudflare.com/ajax/libs/sakana-widget/2.7.0/sakana.min.js -->

<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/[email protected]/lib/sakana.min.css"
/>
<div id="sakana-widget"></div>
<script>
  function initSakanaWidget() {
    new SakanaWidget().mount('#sakana-widget');
  }
</script>
<script
  async
  onload="initSakanaWidget()"
  src="https://cdn.jsdelivr.net/npm/[email protected]/lib/sakana.min.js"
></script>
// npm install --save sakana-widget
import 'sakana-widget/lib/index.css';
import SakanaWidget from 'sakana-widget';
new SakanaWidget().mount('#sakana-widget');

This package exports a class SakanaWidget by default, through which a widget can be initialized. The code above initializes a widget with default settings and mounts it to the #sakana-widget element.

You can continue to create widget instances and mount to more DOM elements, where the data is completely independent between widgets except for roles, and non-static methods support chaining calls.

For example, you can modify some settings before mounting a widget and get a super-slow Chisato:

new SakanaWidget().setState({ i: 0.001, d: 1 }).mount('#sakana-widget');

Or, get the built-in character object via the getCharacter static method, modify the parameters, and create a super-slow, non-damped (perpetual) Takina as a new character:

const takina = SakanaWidget.getCharacter('takina');
takina.initialState = {
  ...takina.initialState,
  i: 0.001,
  d: 1,
};
SakanaWidget.registerCharacter('takina-slow', takina);
new SakanaWidget({ character: 'takina-slow' }).mount('#sakana-widget');

Of course, you can use your own image (url or base64) as a character, e.g. GitHub's icon:

const github = SakanaWidget.getCharacter('chisato');
github.image = `https://raw.githubusercontent.com/dsrkafuu/sakana-widget/main/docs/github.png`;
SakanaWidget.registerCharacter('github', github);
new SakanaWidget({ character: 'github' }).mount('#sakana-widget');

See the API section below for detailed parameters and class type.

Auto Resizing

Set autoFit: true when initializing the component and it will automatically scale according to the size of its mount container, minimum 120px.

Note that to turn on auto-scaling you need to make sure the mounting container is a BFC, the easiest way to do this is to set position: relative or position: fixed. Components in auto-scaling mode additionally add a wrapper container between the app and the mount container, and set its width and height to 100% by which the actual size is detected, so the BFC is required.

API

Types

export interface SakanaWidgetState {
  /**
   * inertia
   */
  i: number;
  /**
   * stickiness
   */
  s: number;
  /**
   * decay
   */
  d: number;
  /**
   * angle
   */
  r: number;
  /**
   * height
   */
  y: number;
  /**
   * vertical speed
   */
  t: number;
  /**
   * horizontal speed
   */
  w: number;
}

export interface SakanaWidgetCharacter {
  image: string;
  initialState: SakanaWidgetState;
}

Constructor Params

export interface SakanaWidgetOptions {
  /**
   * widget size, default to `200`
   */
  size?: number;
  /**
   * auto fit size (120px minimum), default to `false`
   */
  autoFit?: boolean;
  /**
   * default character, default to `chisato`
   */
  character?: 'chisato' | 'takina';
  /**
   * controls bar, default to `true`
   */
  controls?: boolean;
  /**
   * show spring rod, default to `true`
   */
  rod?: boolean;
  /**
   * character draggable, default to `true`
   */
  draggable?: boolean;
  /**
   * canvas stroke settings, default to `#b4b4b4` & `10`
   */
  stroke?: {
    color?: string;
    width?: number;
  };
  /**
   * motion stop threshold, default to `0.1`
   */
  threshold?: number;
  /**
   * rotate origin, default to `0`
   */
  rotate?: number;
  /**
   * enable accessibility title feature, default to `false`
   */
  title?: boolean;
}

Widget Instance

class SakanaWidget {
  /**
   * get data of a registered character
   */
  static getCharacter(name: string): SakanaWidgetCharacter | null;
  /**
   * get all registered character
   */
  static getCharacters();
  /**
   * registered a new character
   */
  static registerCharacter(name: string, character: SakanaWidgetCharacter);
  /**
   * set current state of widget
   */
  setState(state: Partial<SakanaWidgetState>);
  /**
   * set current character of widget
   */
  setCharacter(name: string);
  /**
   * set to next character of widget
   */
  nextCharacter();
  /**
   * switch the auto mode
   */
  triggetAutoMode();
  /**
   * mount the widget
   */
  mount(el: HTMLElement | string);
  /**
   * unmount the widget
   */
  unmount();
}

License

Released under MIT License, please note that the 2 default images should not be used for any commercial activities. This project used to be a secondary development based on https://github.com/itorr/sakana.

Image source: 大伏アオ @blue00f4 pixiv

sakana-widget's People

Contributors

dsrkafuu avatar pinkchampagne17 avatar prosperbao avatar swingcosmic avatar yunjin77 avatar zhushenwudi 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

sakana-widget's Issues

SakanaWidget.getCharacter() 方法无法获取角色

你好,我想生成一个默认静止的chisato,但是无法获取,代码如下

function initSakanaWidget() {
  const characters = SakanaWidget.getCharacters()
  console.log(characters) // 这里打印是空角色池
  const chisato = SakanaWidget.getCharacter('chisato');
  chisato.initialState = {
    ...chisato.initialState,
    i: 0,
    d: 0
  }
  SakanaWidget.registerCharacter('chisato-silence', chisato);
  new SakanaWidget({
    character: 'chisato-silence',
    autoFit: true,
    controls: false
  }).mount('#sakana-widget')
}
Uncaught TypeError: Cannot read properties of null (reading 'chisato')
    at Q.getCharacter (index.ts:107:19)
    at initSakanaWidget (index.html:16:38)
    at HTMLScriptElement.onload (index.html:36:6)

can not use with vite-ssg

Not sure which is causing the problem, come here for help, thank you.

[vite-ssg] An internal error occurred.
[vite-ssg] Please report an issue, if none already exists: https://github.com/antfu/vite-ssg/issues
/home/hyoban/dev/ssg-sakana/node_modules/.pnpm/[email protected]/node_modules/sakana-widget/lib/index.js:10
})(self, () => {
   ^

ReferenceError: self is not defined
    at Object.<anonymous> (/home/hyoban/dev/ssg-sakana/node_modules/.pnpm/[email protected]/node_modules/sakana-widget/lib/index.js:10:4)
    at Module._compile (node:internal/modules/cjs/loader:1105:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:170:29)
    at ModuleJob.run (node:internal/modules/esm/module_job:198:25)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:385:24)
    at async build (file:///home/hyoban/dev/ssg-sakana/node_modules/.pnpm/[email protected]_thgl23324gg75myoeph36y4c5a/node_modules/vite-ssg/dist/chunks/build.mjs:171:87)
 ELIFECYCLE  Command failed with exit code 1.

minimal reproduction

https://github.com/hyoban/ssg-sakana

https://github.com/hyoban/ssg-sakana/commit/e99b063fb1630df60e064a9c6211c26ac12001a0

关于自定义组件

如果参考 README 的这一段使用说明:

const takina = SakanaWidget.getCharacter('takina');
takina.initialState = {
  ...takina.initialState,
  i: 0.001,
  d: 1,
};
SakanaWidget.registerCharacter('takina-slow', takina);
new SakanaWidget({ character: 'takina-slow' }).mount('#sakana-widget');

会发现切换角色后,原来的 takina 也跟着变慢了,应该不是很符合预期?

不太确定这里的 cloneDeep 用意是不是这个

// register default characters
const _characters: { [key: string]: SakanaWidgetCharacter } = {};
(Object.keys(characters) as Array<keyof typeof characters>).forEach((key) => {
const _char = characters[key];
_characters[key] = cloneDeep(_char);
});

如果是的话,考虑设置一下 proxy?

// register default characters 
const _characters: { [key: string]: SakanaWidgetCharacter } = {};
(Object.keys(characters) as Array<keyof typeof characters>).forEach((key) => {
  const _char = characters[key];
  _characters[key] = _char;
  Object.defineProperty(_characters, key, {
    get: () => cloneDeep(_char),
  });
});

TypeError: Object.defineProperty called on non-object

vue3中使用npm run serve时编译无异常,但该组件无法正常工作,控制台报错如下
屏幕截图 2022-09-11 155103
使用build打包后能正常工作,指定serve环境为production或test时亦能正常工作,serve环境为默认项development时出现问题
使用 import SakanaWidget from 'sakana-widget'; 直接导入

onMounted(() => {
  import('sakana-widget').then((pkg) => {
    const SakanaWidget = pkg.default
    new SakanaWidget().mount('#sakana-widget')
  });
});

导入均出现此错误
版本信息:
sakana-widget:2.3.0
vue:3.2.38

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.