├── .clean-publish
├── .codeclimate.yml
├── .commitlintrc.json
├── .czrc
├── .editorconfig
├── .eslintrc.cjs
├── .github
├── CONTRIBUTING.md
├── FUNDING.yml
├── ISSUE_TEMPLATE
│ ├── bug-report.yml
│ ├── config.yml
│ └── feature-request.yml
├── renovate.json
└── workflows
│ ├── checks.yml
│ ├── ci.yml
│ ├── commit.yml
│ ├── release.yml
│ └── website.yml
├── .gitignore
├── .nano-staged.json
├── .npmrc
├── .prettierrc
├── .simple-git-hooks.json
├── .size-limit.json
├── .storybook
├── main.js
├── manager.js
├── package.json
├── preview.js
└── theme.js
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── assets
├── bar.png
├── bubble.png
├── donate.svg
├── doughnut.png
├── line.png
├── logo.png
├── pie.png
├── polar.png
├── radar.png
├── scatter.png
├── vue-chartjs.png
└── vue-chartjs.svg
├── codecov.yml
├── package.json
├── pnpm-lock.yaml
├── rollup.config.js
├── sandboxes
├── bar
│ ├── index.html
│ ├── index.ts
│ ├── package.json
│ ├── src
│ │ ├── App.vue
│ │ └── chartConfig.ts
│ └── vite.config.js
├── bubble
│ ├── index.html
│ ├── index.ts
│ ├── package.json
│ ├── src
│ │ ├── App.vue
│ │ └── chartConfig.ts
│ └── vite.config.js
├── custom
│ ├── index.html
│ ├── index.ts
│ ├── package.json
│ ├── src
│ │ ├── App.vue
│ │ ├── chartConfig.ts
│ │ └── components
│ │ │ └── LineWithLineChart.ts
│ └── vite.config.js
├── doughnut
│ ├── index.html
│ ├── index.ts
│ ├── package.json
│ ├── src
│ │ ├── App.vue
│ │ └── chartConfig.ts
│ └── vite.config.js
├── events
│ ├── index.html
│ ├── index.ts
│ ├── package.json
│ ├── src
│ │ ├── App.vue
│ │ └── chartConfig.ts
│ └── vite.config.js
├── line
│ ├── index.html
│ ├── index.ts
│ ├── package.json
│ ├── src
│ │ ├── App.vue
│ │ └── chartConfig.ts
│ └── vite.config.js
├── pie
│ ├── index.html
│ ├── index.ts
│ ├── package.json
│ ├── src
│ │ ├── App.vue
│ │ └── chartConfig.ts
│ └── vite.config.js
├── polar-area
│ ├── index.html
│ ├── index.ts
│ ├── package.json
│ ├── src
│ │ ├── App.vue
│ │ └── chartConfig.ts
│ └── vite.config.js
├── radar
│ ├── index.html
│ ├── index.ts
│ ├── package.json
│ ├── src
│ │ ├── App.vue
│ │ └── chartConfig.ts
│ └── vite.config.js
├── reactive
│ ├── index.html
│ ├── index.ts
│ ├── package.json
│ ├── src
│ │ ├── App.vue
│ │ └── chartConfig.ts
│ └── vite.config.js
├── scatter
│ ├── index.html
│ ├── index.ts
│ ├── package.json
│ ├── src
│ │ ├── App.vue
│ │ └── chartConfig.ts
│ └── vite.config.js
└── tsconfig.json
├── src
├── chart.ts
├── index.ts
├── props.ts
├── typedCharts.ts
├── types.ts
└── utils.ts
├── stories
├── bar.stories.ts
├── bubble.stories.ts
├── chart.stories.ts
├── custom.stories.ts
├── doughnut.stories.ts
├── line.stories.ts
├── pie.stories.ts
├── polarArea.stories.ts
├── radar.stories.ts
├── reactive.stories.ts
└── scatter.stories.ts
├── test
├── Bar.spec.ts
├── Bubble.spec.ts
├── Doughnut.spec.ts
├── Line.spec.ts
├── Pie.spec.ts
├── PolarArea.spec.ts
├── Radar.spec.ts
├── Scatter.spec.ts
├── setup.js
└── types.test-d.ts
├── tsconfig.json
├── vite.config.js
└── website
├── package.json
├── pnpm-lock.yaml
└── src
├── .vitepress
└── config.ts
├── CNAME
├── api
└── index.md
├── examples
└── index.md
├── guide
└── index.md
├── images
└── vue-chartjs.png
├── index.md
├── ja
├── api
│ └── index.md
├── guide
│ └── index.md
└── index.md
├── kr
├── api
│ └── index.md
├── guide
│ └── index.md
└── index.md
├── migration-guides
└── index.md
├── package.json
├── pt-br
├── api
│ └── index.md
├── guide
│ └── index.md
└── index.md
├── ru
├── api
│ └── index.md
├── guide
│ └── index.md
└── index.md
└── zh-cn
├── api
└── index.md
├── guide
└── index.md
└── index.md
/.clean-publish:
--------------------------------------------------------------------------------
1 | {
2 | "withoutPublish": true,
3 | "tempDir": "package",
4 | "fields": ["tsd"],
5 | "files": ["website"]
6 | }
7 |
--------------------------------------------------------------------------------
/.codeclimate.yml:
--------------------------------------------------------------------------------
1 | engines:
2 | eslint:
3 | enabled: true
4 | duplication:
5 | enabled: true
6 | config:
7 | languages:
8 | - javascript:
9 | ratings:
10 | paths:
11 | - "**.js"
12 | exclude_paths:
13 | - "dist/"
14 | - "test/**/*"
15 | - "es/"
16 | - "build/"
17 | - "config/"
18 |
--------------------------------------------------------------------------------
/.commitlintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["@commitlint/config-conventional"],
3 | "rules": {
4 | "body-max-line-length": [0]
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/.czrc:
--------------------------------------------------------------------------------
1 | {
2 | "path": "./node_modules/cz-conventional-changelog"
3 | }
4 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # This file is for unifying the coding style for different editors and IDEs
2 | # editorconfig.org
3 | root = true
4 |
5 | [*]
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 | indent_style = space
11 | indent_size = 2
12 |
--------------------------------------------------------------------------------
/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | parserOptions: {
4 | sourceType: 'module'
5 | },
6 | // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style
7 | extends: [
8 | 'standard',
9 | 'plugin:prettier/recommended',
10 | 'plugin:vue/recommended',
11 | 'plugin:prettier-vue/recommended',
12 | 'plugin:vue/vue3-essential',
13 | '@vue/eslint-config-typescript'
14 | ],
15 | // required to lint *.vue files
16 | plugins: ['prettier'],
17 | // add your custom rules here
18 | rules: {
19 | // allow paren-less arrow functions
20 | 'arrow-parens': 0,
21 | // allow debugger during development
22 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
23 | 'prettier/prettier': 'error',
24 | quotes: [2, 'single', 'avoid-escape']
25 | },
26 | overrides: [
27 | {
28 | files: ['sandboxes/**/*', 'test/**/*'],
29 | rules: {
30 | 'vue/no-reserved-component-names': 'off'
31 | }
32 | }
33 | ],
34 | ignorePatterns: ['dist/**/*', 'node_modules/**/*', 'rollup.config.js']
35 | }
36 |
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | Thank you for contributing vue-chartjs!
2 | =========================================
3 |
4 | Please follow this steps:
5 |
6 | 1. Fork it ( https://github.com/apertureless/vue-chartjs/fork )
7 | 2. Create your feature branch (`git checkout -b my-new-feature`)
8 | 3. Commit your changes (`git commit -am 'Add some feature'`)
9 | 4. Push to the branch (`git push origin my-new-feature`)
10 | 5. Create a new Pull Request
11 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: apertureless
2 | ko_fi: apertureless
3 | custom: ["paypal.me/apertureless"]
4 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug-report.yml:
--------------------------------------------------------------------------------
1 | name: "🐛 Bug Report"
2 | description: "If something isn't working as expected."
3 | title: "[Bug]: "
4 | labels: ["bug"]
5 | body:
6 | - type: markdown
7 | attributes:
8 | value: Thanks for taking the time to file a bug report! Please fill out this form as completely as possible.
9 |
10 | - type: markdown
11 | attributes:
12 | value: ⚠️ vue-chartjs is just the wrapper around Chart.js, so if you are experiencing an issue with charts rendering, please create a related issue in [Chart.js repository](https://github.com/chartjs/Chart.js/issues).
13 |
14 | - type: checkboxes
15 | id: input1
16 | attributes:
17 | label: Would you like to work on a fix?
18 | options:
19 | - label: Check this if you would like to implement a PR, we are more than happy to help you go through the process.
20 |
21 | - type: textarea
22 | attributes:
23 | label: Current and expected behavior
24 | description: A clear and concise description of what the library is doing and what you would expect.
25 | validations:
26 | required: true
27 |
28 | - type: input
29 | attributes:
30 | label: Reproduction
31 | description: |
32 | Please provide issue reproduction.
33 | You can give a link to a repository with the reproduction or make a fork of [this sandbox](https://stackblitz.com/github/apertureless/vue-chartjs/tree/main/sandboxes/bar) and reproduce the issue there.
34 | validations:
35 | required: true
36 |
37 | - type: input
38 | attributes:
39 | label: chart.js version
40 | description: Which version of `chart.js` are you using?
41 | placeholder: v0.0.0
42 | validations:
43 | required: true
44 |
45 | - type: input
46 | attributes:
47 | label: vue-chartjs version
48 | description: Which version of `vue-chartjs` are you using?
49 | placeholder: v0.0.0
50 | validations:
51 | required: true
52 |
53 | - type: textarea
54 | attributes:
55 | label: Possible solution
56 | description: If you have suggestions on a fix for the bug.
57 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 |
2 | blank_issues_enabled: false
3 | contact_links:
4 | - name: 🤔 Have a Question?
5 | url: https://stackoverflow.com/questions/tagged/vue-chartjs/
6 | about: Feel free to ask questions on Stack Overflow.
7 | - name: 📊 Have a Problem With Chart.js?
8 | url: https://github.com/chartjs/Chart.js/issues
9 | about: vue-chartjs is just the wrapper around Chart.js, so if you are experiencing an issue with charts rendering, please create a related issue in Chart.js repository.
10 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature-request.yml:
--------------------------------------------------------------------------------
1 | name: "🚀 Feature Request"
2 | description: "I have a specific suggestion!"
3 | labels: ["enhancement"]
4 | body:
5 | - type: markdown
6 | attributes:
7 | value: Thanks for taking the time to suggest a new feature! Please fill out this form as completely as possible.
8 |
9 | - type: markdown
10 | attributes:
11 | value: ⚠️ vue-chartjs is just the wrapper around Chart.js, so if you are experiencing an issue with charts rendering, please create a related issue in [Chart.js repository](https://github.com/chartjs/Chart.js/issues).
12 |
13 | - type: checkboxes
14 | id: input1
15 | attributes:
16 | label: Would you like to work on this feature?
17 | options:
18 | - label: Check this if you would like to implement a PR, we are more than happy to help you go through the process.
19 |
20 | - type: textarea
21 | attributes:
22 | label: What problem are you trying to solve?
23 | description: |
24 | A concise description of what the problem is.
25 | placeholder: |
26 | I have an issue when [...]
27 | validations:
28 | required: true
29 |
30 | - type: textarea
31 | attributes:
32 | label: Describe the solution you'd like
33 | validations:
34 | required: true
35 |
36 | - type: textarea
37 | attributes:
38 | label: Describe alternatives you've considered
39 |
40 | - type: textarea
41 | attributes:
42 | label: Documentation, Adoption, Migration Strategy
43 | description: |
44 | If you can, explain how users will be able to use this and how it might be documented. Maybe a mock-up?
45 |
--------------------------------------------------------------------------------
/.github/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "config:base",
4 | ":preserveSemverRanges"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/.github/workflows/checks.yml:
--------------------------------------------------------------------------------
1 | name: Checks
2 | on:
3 | pull_request:
4 | branches:
5 | - main
6 | jobs:
7 | typings:
8 | runs-on: ubuntu-latest
9 | name: typings
10 | steps:
11 | - name: Checkout the repository
12 | uses: actions/checkout@v4
13 | - name: Install pnpm
14 | uses: pnpm/action-setup@v2
15 | with:
16 | version: 8
17 | - name: Install Node.js
18 | uses: actions/setup-node@v4
19 | with:
20 | node-version: 16
21 | cache: 'pnpm'
22 | - name: Install dependencies
23 | run: pnpm install
24 | - name: Prebuild
25 | run: pnpm build
26 | - name: Check typings
27 | if: success()
28 | run: pnpm test:typings
29 | storybook:
30 | runs-on: ubuntu-latest
31 | name: storybook
32 | steps:
33 | - name: Checkout the repository
34 | uses: actions/checkout@v4
35 | - name: Install pnpm
36 | uses: pnpm/action-setup@v2
37 | with:
38 | version: 8
39 | - name: Install Node.js
40 | uses: actions/setup-node@v4
41 | with:
42 | node-version: 16
43 | cache: 'pnpm'
44 | - name: Install dependencies
45 | run: pnpm install
46 | - name: Check storybook
47 | run: pnpm build:storybook
48 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on:
3 | push:
4 | pull_request:
5 | jobs:
6 | test:
7 | runs-on: ubuntu-latest
8 | name: Running tests
9 | steps:
10 | - name: Checkout the repository
11 | uses: actions/checkout@v4
12 | - name: Install pnpm
13 | uses: pnpm/action-setup@v2
14 | with:
15 | version: 8
16 | - name: Install Node.js
17 | uses: actions/setup-node@v4
18 | with:
19 | node-version: 16
20 | cache: 'pnpm'
21 | - name: Install dependencies
22 | run: pnpm install
23 | - name: Run tests
24 | run: pnpm test
25 |
--------------------------------------------------------------------------------
/.github/workflows/commit.yml:
--------------------------------------------------------------------------------
1 | name: Commit
2 | on:
3 | push:
4 | jobs:
5 | conventional-commit:
6 | runs-on: ubuntu-latest
7 | name: Checking commit name
8 | steps:
9 | - name: Checkout the repository
10 | uses: actions/checkout@v4
11 | with:
12 | fetch-depth: 0
13 | - name: Run commitlint
14 | uses: wagoid/commitlint-github-action@v5
15 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 | on:
3 | release:
4 | types: [created]
5 | jobs:
6 | build:
7 | runs-on: ubuntu-latest
8 | name: Publish package
9 | steps:
10 | - name: Checkout the repository
11 | uses: actions/checkout@v4
12 | - name: Install pnpm
13 | uses: pnpm/action-setup@v2
14 | with:
15 | version: 8
16 | - name: Install Node.js
17 | uses: actions/setup-node@v4
18 | with:
19 | node-version: 16
20 | cache: 'pnpm'
21 | registry-url: 'https://registry.npmjs.org'
22 | - name: Install dependencies
23 | run: pnpm install
24 | - name: Publish
25 | run: pnpm publish --no-git-checks
26 | env:
27 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
28 |
--------------------------------------------------------------------------------
/.github/workflows/website.yml:
--------------------------------------------------------------------------------
1 | name: Website
2 | on:
3 | push:
4 | branches:
5 | - main
6 | jobs:
7 | deploy:
8 | runs-on: ubuntu-latest
9 | name: deploy website
10 | steps:
11 | - name: Checkout the repository
12 | uses: actions/checkout@v4
13 | - name: Install pnpm
14 | uses: pnpm/action-setup@v2
15 | with:
16 | version: 8
17 | - name: Install Node.js
18 | uses: actions/setup-node@v4
19 | with:
20 | node-version: 16
21 | cache: 'pnpm'
22 | - name: Install dependencies
23 | run: pnpm install
24 | - name: Install website dependencies
25 | run: pnpm install
26 | working-directory: ./website
27 | - name: Build website
28 | run: pnpm build
29 | working-directory: ./website
30 | - name: Make CNAME file
31 | run: |
32 | cd ./website/src/.vitepress/dist
33 | echo "vue-chartjs.org" > CNAME
34 | - name: Prepare build
35 | run: |
36 | cd ./website/src/.vitepress/dist
37 | git init
38 | git add -A
39 | git config --local user.email "action@github.com"
40 | git config --local user.name "GitHub Action"
41 | git commit -m 'deploy'
42 | - name: Push build
43 | uses: ad-m/github-push-action@master
44 | with:
45 | github_token: ${{ secrets.GITHUB_TOKEN }}
46 | branch: gh-pages
47 | force: true
48 | directory: ./website/src/.vitepress/dist
49 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | node_modules
5 |
6 | # builds
7 | dist
8 | package
9 | storybook-static
10 |
11 | # misc
12 | .DS_Store
13 |
14 | npm-debug.log*
15 |
16 | # testing
17 | coverage
18 |
--------------------------------------------------------------------------------
/.nano-staged.json:
--------------------------------------------------------------------------------
1 | {
2 | "**/*.{js,ts,vue}": ["prettier --write", "eslint"]
3 | }
4 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | strict-peer-dependencies=false
2 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "jsxSingleQuote": true,
4 | "semi": false,
5 | "tabWidth": 2,
6 | "bracketSpacing": true,
7 | "arrowParens": "avoid",
8 | "trailingComma": "none"
9 | }
10 |
--------------------------------------------------------------------------------
/.simple-git-hooks.json:
--------------------------------------------------------------------------------
1 | {
2 | "commit-msg": "pnpm commitlint --edit \"$1\"",
3 | "pre-commit": "pnpm nano-staged",
4 | "pre-push": "pnpm test"
5 | }
6 |
--------------------------------------------------------------------------------
/.size-limit.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "path": "dist/index.js",
4 | "limit": "2.95 KB",
5 | "webpack": false,
6 | "running": false
7 | },
8 | {
9 | "path": "dist/index.js",
10 | "limit": "1.5 KB",
11 | "import": "{ Bar }"
12 | }
13 | ]
14 |
--------------------------------------------------------------------------------
/.storybook/main.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const { mergeConfig } = require('vite')
3 |
4 | module.exports = {
5 | core: {
6 | builder: '@storybook/builder-vite'
7 | },
8 | viteFinal(config) {
9 | return mergeConfig(config, {
10 | resolve: {
11 | dedupe: ['@storybook/client-api'],
12 | alias: {
13 | 'vue-chartjs': path.resolve(__dirname, '../src')
14 | }
15 | }
16 | })
17 | },
18 | framework: '@storybook/vue3',
19 | stories: ['../stories/*.stories.@(ts|js)'],
20 | addons: [
21 | '@storybook/addon-docs',
22 | '@storybook/addon-controls',
23 | '@storybook/addon-actions'
24 | ]
25 | }
26 |
--------------------------------------------------------------------------------
/.storybook/manager.js:
--------------------------------------------------------------------------------
1 | import { addons } from '@storybook/addons'
2 |
3 | import { theme } from './theme.js'
4 |
5 | addons.setConfig({
6 | theme,
7 | panelPosition: 'right'
8 | })
9 |
--------------------------------------------------------------------------------
/.storybook/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "commonjs"
3 | }
4 |
--------------------------------------------------------------------------------
/.storybook/preview.js:
--------------------------------------------------------------------------------
1 | import { configureActions } from '@storybook/addon-actions'
2 |
3 | configureActions({
4 | depth: 5
5 | })
6 |
--------------------------------------------------------------------------------
/.storybook/theme.js:
--------------------------------------------------------------------------------
1 | import { create } from '@storybook/theming'
2 |
3 | export const theme = create({
4 | base: 'light',
5 | brandTitle: 'vue-chartjs',
6 | brandUrl: 'https://github.com/apertureless/vue-chartjs'
7 | })
8 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Code of Conduct
2 |
3 | As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4 |
5 | We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.
6 |
7 | Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
8 |
9 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
10 |
11 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
12 |
13 | This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
14 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Jakub Juszczak
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vue-chartjs
2 |
3 |
4 |
5 | **vue-chartjs** is a wrapper for [Chart.js](https://github.com/chartjs/Chart.js) in Vue. You can easily create reuseable chart components.
6 |
7 | Supports Chart.js v4.
8 |
9 | [](https://badge.fury.io/js/vue-chartjs)
10 | [](https://codecov.io/gh/apertureless/vue-chartjs)
11 | [](https://github.com/apertureless/vue-chartjs/actions)
12 | [](http://packagequality.com/#?package=vue-chartjs)
13 | [](https://www.npmjs.com/package/vue-chartjs)
14 | [](https://gitter.im/vue-chartjs/Lobby)
15 | [](https://github.com/apertureless/vue-chartjs/blob/master/LICENSE.txt)
16 | [](https://cdnjs.com/libraries/vue-chartjs)
17 | [](https://snyk.io/test/github/apertureless/vue-chartjs)
18 | [](https://www.paypal.me/apertureless/50eur)
19 | [](https://ko-fi.com/C0C1WP7C)
20 |
21 |
22 | QuickStart
23 | •
24 | Docs
25 | •
26 | Stack Overflow
27 |
28 |
29 |
30 | ## Quickstart
31 |
32 | Install this library with peer dependencies:
33 |
34 | ```bash
35 | pnpm add vue-chartjs chart.js
36 | # or
37 | yarn add vue-chartjs chart.js
38 | # or
39 | npm i vue-chartjs chart.js
40 | ```
41 |
42 | Then, import and use individual components:
43 |
44 | ```vue
45 |
46 |
47 |
48 |
49 |
81 | ```
82 |
83 |
84 |
85 | Need an API to fetch data? Consider [Cube](https://cube.dev/?ref=eco-vue-chartjs), an open-source API for data apps.
86 |
87 |
88 |
89 | [](https://cube.dev/?ref=eco-vue-chartjs)
90 |
91 | ## Docs
92 |
93 | - [Reactivity](https://vue-chartjs.org/guide/#updating-charts)
94 | - [Access to Chart instance](https://vue-chartjs.org/guide/#access-to-chart-instance)
95 | - [Accessibility](https://vue-chartjs.org/guide/#accessibility)
96 | - [Migration from v4 to v5](https://vue-chartjs.org/migration-guides/#migration-from-v4-to-v5/)
97 | - [Migration from vue-chart-3](https://vue-chartjs.org/migration-guides/#migration-from-vue-chart-3/)
98 | - [API](https://vue-chartjs.org/api/)
99 | - [Examples](https://vue-chartjs.org/examples/)
100 |
101 | ## Build Setup
102 |
103 | ``` bash
104 | # install dependencies
105 | pnpm install
106 |
107 | # build for production with minification
108 | pnpm build
109 |
110 | # run unit tests
111 | pnpm test:unit
112 |
113 | # run all tests
114 | pnpm test
115 | ```
116 |
117 | ## Contributing
118 |
119 | 1. Fork it ( https://github.com/apertureless/vue-chartjs/fork )
120 | 2. Create your feature branch (`git checkout -b my-new-feature`)
121 | 3. Commit your changes (`git commit -am 'Add some feature'`)
122 | 4. Push to the branch (`git push origin my-new-feature`)
123 | 5. Create a new Pull Request
124 |
125 | ## License
126 |
127 | This software is distributed under [MIT license](LICENSE.txt).
128 |
129 |
130 |
--------------------------------------------------------------------------------
/assets/bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lu0415mc/vue-chartjs/d52075bdf18a718a2dc3dc220888198e46a81b67/assets/bar.png
--------------------------------------------------------------------------------
/assets/bubble.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lu0415mc/vue-chartjs/d52075bdf18a718a2dc3dc220888198e46a81b67/assets/bubble.png
--------------------------------------------------------------------------------
/assets/donate.svg:
--------------------------------------------------------------------------------
1 |
2 | Donate Donate
3 |
--------------------------------------------------------------------------------
/assets/doughnut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lu0415mc/vue-chartjs/d52075bdf18a718a2dc3dc220888198e46a81b67/assets/doughnut.png
--------------------------------------------------------------------------------
/assets/line.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lu0415mc/vue-chartjs/d52075bdf18a718a2dc3dc220888198e46a81b67/assets/line.png
--------------------------------------------------------------------------------
/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lu0415mc/vue-chartjs/d52075bdf18a718a2dc3dc220888198e46a81b67/assets/logo.png
--------------------------------------------------------------------------------
/assets/pie.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lu0415mc/vue-chartjs/d52075bdf18a718a2dc3dc220888198e46a81b67/assets/pie.png
--------------------------------------------------------------------------------
/assets/polar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lu0415mc/vue-chartjs/d52075bdf18a718a2dc3dc220888198e46a81b67/assets/polar.png
--------------------------------------------------------------------------------
/assets/radar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lu0415mc/vue-chartjs/d52075bdf18a718a2dc3dc220888198e46a81b67/assets/radar.png
--------------------------------------------------------------------------------
/assets/scatter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lu0415mc/vue-chartjs/d52075bdf18a718a2dc3dc220888198e46a81b67/assets/scatter.png
--------------------------------------------------------------------------------
/assets/vue-chartjs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lu0415mc/vue-chartjs/d52075bdf18a718a2dc3dc220888198e46a81b67/assets/vue-chartjs.png
--------------------------------------------------------------------------------
/assets/vue-chartjs.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | codecov:
2 | branch: master
3 |
4 | coverage:
5 | precision: 2
6 | round: down
7 | range: "70...100"
8 |
9 | status:
10 | project:
11 | default:
12 | target: auto
13 | threshold: null
14 | branches: null
15 |
16 | patch:
17 | default:
18 | target: auto
19 | branches: null
20 |
21 | changes:
22 | default:
23 | branches: null
24 |
25 | ignore:
26 | - "tests/*"
27 | - "sandboxes/*"
28 | - "stories/*"
29 |
30 |
31 | comment:
32 | layout: "header, diff, changes, sunburst, uncovered, tree"
33 | branches: null
34 | behavior: default
35 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-chartjs",
3 | "type": "module",
4 | "version": "5.3.0",
5 | "description": "Vue.js wrapper for chart.js for creating beautiful charts.",
6 | "author": "Jakub Juszczak ",
7 | "homepage": "http://vue-chartjs.org",
8 | "license": "MIT",
9 | "contributors": [
10 | {
11 | "name": "Thorsten Lünborg",
12 | "web": "https://github.com/LinusBorg"
13 | },
14 | {
15 | "name": "Juan Carlos Alonso",
16 | "web": "https://github.com/jcalonso"
17 | }
18 | ],
19 | "maintainers": [
20 | {
21 | "name": "Jakub Juszczak",
22 | "email": "jakub@posteo.de",
23 | "web": "http://www.jakubjuszczak.de"
24 | }
25 | ],
26 | "repository": {
27 | "type": "git",
28 | "url": "git+ssh://git@github.com:apertureless/vue-chartjs.git"
29 | },
30 | "bugs": {
31 | "url": "https://github.com/apertureless/vue-chartjs/issues"
32 | },
33 | "keywords": [
34 | "ChartJs",
35 | "Vue",
36 | "Visualisation",
37 | "Wrapper",
38 | "Charts"
39 | ],
40 | "sideEffects": false,
41 | "types": "./dist/index.d.ts",
42 | "exports": "./src/index.ts",
43 | "publishConfig": {
44 | "main": "./dist/index.cjs",
45 | "module": "./dist/index.js",
46 | "exports": {
47 | "types": "./dist/index.d.ts",
48 | "import": "./dist/index.js",
49 | "require": "./dist/index.cjs"
50 | },
51 | "directory": "package"
52 | },
53 | "files": [
54 | "dist"
55 | ],
56 | "scripts": {
57 | "prepublishOnly": "pnpm test && pnpm build && del ./package && clean-publish",
58 | "postpublish": "del ./package",
59 | "emitDeclarations": "tsc --emitDeclarationOnly",
60 | "build": "rollup -c & pnpm emitDeclarations",
61 | "start:storybook": "start-storybook -p 6006 --ci",
62 | "build:storybook": "del ./storybook-static; NODE_ENV=production build-storybook",
63 | "lint": "eslint 'sandboxes/**/*.{js,ts,vue}' 'src/**/*.{js,ts,vue}' 'stories/**/*.{js,ts,vue}' 'test/**/*.{js,ts,vue}'",
64 | "test:unit": "vitest run --coverage",
65 | "test:unit:watch": "vitest watch",
66 | "test:typings": "tsd",
67 | "test:size": "size-limit",
68 | "test": "pnpm lint && pnpm test:unit",
69 | "format": "prettier --write src test sandboxes stories",
70 | "commit": "cz",
71 | "bumpVersion": "standard-version",
72 | "createGithubRelease": "simple-github-release",
73 | "release": "pnpm bumpVersion && git push origin main --tags && pnpm createGithubRelease",
74 | "updateGitHooks": "simple-git-hooks"
75 | },
76 | "peerDependencies": {
77 | "chart.js": "^4.1.1",
78 | "vue": "^3.0.0-0 || ^2.7.0"
79 | },
80 | "devDependencies": {
81 | "@commitlint/cli": "^18.0.0",
82 | "@commitlint/config-conventional": "^18.0.0",
83 | "@rollup/plugin-node-resolve": "^15.0.1",
84 | "@size-limit/preset-big-lib": "^11.0.0",
85 | "@storybook/addon-actions": "^6.5.13",
86 | "@storybook/addon-controls": "^6.5.13",
87 | "@storybook/addon-docs": "^6.5.13",
88 | "@storybook/addons": "^6.5.13",
89 | "@storybook/builder-vite": "^0.4.0",
90 | "@storybook/client-api": "^6.5.13",
91 | "@storybook/client-logger": "^6.5.13",
92 | "@storybook/vue3": "^6.5.14",
93 | "@swc/core": "^1.3.23",
94 | "@swc/helpers": "^0.5.0",
95 | "@vitejs/plugin-vue": "^4.0.0",
96 | "@vitest/coverage-c8": "^0.31.0",
97 | "@vue/eslint-config-typescript": "^12.0.0",
98 | "@vue/test-utils": "^2.0.0-rc.17",
99 | "browserslist": "^4.19.1",
100 | "chart.js": "^4.4.1",
101 | "clean-publish": "^4.0.0",
102 | "commitizen": "^4.2.4",
103 | "cross-env": "^7.0.0",
104 | "cz-conventional-changelog": "3.3.0",
105 | "del-cli": "^5.0.0",
106 | "eslint": "8.55.0",
107 | "eslint-config-prettier": "^9.0.0",
108 | "eslint-config-standard": "^17.0.0",
109 | "eslint-plugin-import": "^2.25.4",
110 | "eslint-plugin-n": "^16.0.0",
111 | "eslint-plugin-node": "^11.1.0",
112 | "eslint-plugin-prettier": "^4.2.1",
113 | "eslint-plugin-prettier-vue": "4.2.0",
114 | "eslint-plugin-promise": "^6.0.0",
115 | "eslint-plugin-vue": "^9.0.0",
116 | "jsdom": "^23.0.0",
117 | "nano-staged": "^0.8.0",
118 | "prettier": "2.8.8",
119 | "react": "^18.2.0",
120 | "react-dom": "^18.2.0",
121 | "rollup": "^3.7.5",
122 | "rollup-plugin-swc3": "^0.11.0",
123 | "simple-git-hooks": "^2.7.0",
124 | "simple-github-release": "^1.0.0",
125 | "size-limit": "^11.0.0",
126 | "standard-version": "^9.3.2",
127 | "tsd": "^0.25.0",
128 | "typescript": "^4.9.4",
129 | "vite": "^4.0.2",
130 | "vitest": "^0.31.0",
131 | "vitest-canvas-mock": "^0.3.0",
132 | "vue": "^3.2.31"
133 | },
134 | "tsd": {
135 | "directory": "./test"
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import { swc } from 'rollup-plugin-swc3'
2 | import { nodeResolve } from '@rollup/plugin-node-resolve'
3 | import pkg from './package.json' assert { type: 'json' }
4 |
5 | const extensions = ['.js', '.ts']
6 | const external = _ => /node_modules/.test(_) && !/@swc\/helpers/.test(_)
7 | const plugins = targets => [
8 | nodeResolve({
9 | extensions
10 | }),
11 | swc({
12 | tsconfig: false,
13 | env: {
14 | targets
15 | },
16 | module: {
17 | type: 'es6'
18 | },
19 | sourceMaps: true
20 | })
21 | ]
22 |
23 | export default {
24 | input: pkg.exports,
25 | plugins: plugins('defaults and supports es6-module'),
26 | external,
27 | output: [
28 | {
29 | file: pkg.publishConfig.exports.import,
30 | format: 'es',
31 | sourcemap: true
32 | },
33 | {
34 | file: pkg.publishConfig.exports.require,
35 | format: 'cjs',
36 | sourcemap: true
37 | }
38 | ]
39 | }
40 |
--------------------------------------------------------------------------------
/sandboxes/bar/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/bar/index.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import App from './src/App.vue'
3 |
4 | createApp(App).mount('#app')
5 |
--------------------------------------------------------------------------------
/sandboxes/bar/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "vue": "^3.2.31",
9 | "vue-chartjs": "^5.0.0"
10 | },
11 | "devDependencies": {
12 | "@vitejs/plugin-vue": "^4.0.0",
13 | "typescript": "^4.9.3",
14 | "vite": "^4.0.0"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/sandboxes/bar/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
30 |
--------------------------------------------------------------------------------
/sandboxes/bar/src/chartConfig.ts:
--------------------------------------------------------------------------------
1 | export const data = {
2 | labels: [
3 | 'January',
4 | 'February',
5 | 'March',
6 | 'April',
7 | 'May',
8 | 'June',
9 | 'July',
10 | 'August',
11 | 'September',
12 | 'October',
13 | 'November',
14 | 'December'
15 | ],
16 | datasets: [
17 | {
18 | label: 'Data One',
19 | backgroundColor: '#f87979',
20 | data: [40, 20, 12, 39, 10, 40, 39, 80, 40, 20, 12, 11]
21 | }
22 | ]
23 | }
24 |
25 | export const options = {
26 | responsive: true,
27 | maintainAspectRatio: false
28 | }
29 |
--------------------------------------------------------------------------------
/sandboxes/bar/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import vue from '@vitejs/plugin-vue'
3 |
4 | export default defineConfig({
5 | plugins: [vue()]
6 | })
7 |
--------------------------------------------------------------------------------
/sandboxes/bubble/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/bubble/index.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import App from './src/App.vue'
3 |
4 | createApp(App).mount('#app')
5 |
--------------------------------------------------------------------------------
/sandboxes/bubble/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "vue": "^3.2.31",
9 | "vue-chartjs": "^5.0.0"
10 | },
11 | "devDependencies": {
12 | "@vitejs/plugin-vue": "^4.0.0",
13 | "typescript": "^4.9.3",
14 | "vite": "^4.0.0"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/sandboxes/bubble/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
28 |
--------------------------------------------------------------------------------
/sandboxes/bubble/src/chartConfig.ts:
--------------------------------------------------------------------------------
1 | export const data = {
2 | datasets: [
3 | {
4 | label: 'Data One',
5 | backgroundColor: '#f87979',
6 | data: [
7 | {
8 | x: 20,
9 | y: 25,
10 | r: 5
11 | },
12 | {
13 | x: 40,
14 | y: 10,
15 | r: 10
16 | },
17 | {
18 | x: 30,
19 | y: 22,
20 | r: 30
21 | }
22 | ]
23 | },
24 | {
25 | label: 'Data Two',
26 | backgroundColor: '#7C8CF8',
27 | data: [
28 | {
29 | x: 10,
30 | y: 30,
31 | r: 15
32 | },
33 | {
34 | x: 20,
35 | y: 20,
36 | r: 10
37 | },
38 | {
39 | x: 15,
40 | y: 8,
41 | r: 30
42 | }
43 | ]
44 | }
45 | ]
46 | }
47 |
48 | export const options = {
49 | responsive: true,
50 | maintainAspectRatio: false
51 | }
52 |
--------------------------------------------------------------------------------
/sandboxes/bubble/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import vue from '@vitejs/plugin-vue'
3 |
4 | export default defineConfig({
5 | plugins: [vue()]
6 | })
7 |
--------------------------------------------------------------------------------
/sandboxes/custom/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/custom/index.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import App from './src/App.vue'
3 |
4 | createApp(App).mount('#app')
5 |
--------------------------------------------------------------------------------
/sandboxes/custom/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "vue": "^3.2.31",
9 | "vue-chartjs": "^5.0.0"
10 | },
11 | "devDependencies": {
12 | "@vitejs/plugin-vue": "^4.0.0",
13 | "typescript": "^4.9.3",
14 | "vite": "^4.0.0"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/sandboxes/custom/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
39 |
--------------------------------------------------------------------------------
/sandboxes/custom/src/chartConfig.ts:
--------------------------------------------------------------------------------
1 | export const data = {
2 | labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
3 | datasets: [
4 | {
5 | label: 'Data One',
6 | backgroundColor: '#f87979',
7 | data: [40, 39, 10, 40, 39, 80, 40]
8 | }
9 | ]
10 | }
11 |
12 | export const options = {
13 | responsive: true,
14 | maintainAspectRatio: false,
15 | tooltips: {
16 | intersect: false
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/sandboxes/custom/src/components/LineWithLineChart.ts:
--------------------------------------------------------------------------------
1 | import { createTypedChart } from 'vue-chartjs'
2 | import { LineController } from 'chart.js'
3 |
4 | class LineWithLineController extends LineController {
5 | static override id = 'line-with-line'
6 |
7 | public override draw() {
8 | super.draw()
9 |
10 | if (this.chart?.tooltip && this.chart.tooltip.opacity > 0) {
11 | const ctx = this.chart.ctx
12 | const x = this.chart.tooltip.x
13 | const topY = this.chart.scales.y.top
14 | const bottomY = this.chart.scales.y.bottom
15 |
16 | // draw line
17 | ctx.save()
18 | ctx.beginPath()
19 | ctx.moveTo(x, topY)
20 | ctx.lineTo(x, bottomY)
21 | ctx.lineWidth = 2
22 | ctx.strokeStyle = '#07C'
23 | ctx.stroke()
24 | ctx.restore()
25 | }
26 | }
27 | }
28 |
29 | const LineWithLineChart = createTypedChart(
30 | 'line-with-line' as 'line',
31 | LineWithLineController
32 | )
33 |
34 | export default LineWithLineChart
35 |
--------------------------------------------------------------------------------
/sandboxes/custom/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import vue from '@vitejs/plugin-vue'
3 |
4 | export default defineConfig({
5 | plugins: [vue()]
6 | })
7 |
--------------------------------------------------------------------------------
/sandboxes/doughnut/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/doughnut/index.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import App from './src/App.vue'
3 |
4 | createApp(App).mount('#app')
5 |
--------------------------------------------------------------------------------
/sandboxes/doughnut/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "vue": "^3.2.31",
9 | "vue-chartjs": "^5.0.0"
10 | },
11 | "devDependencies": {
12 | "@vitejs/plugin-vue": "^4.0.0",
13 | "typescript": "^4.9.3",
14 | "vite": "^4.0.0"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/sandboxes/doughnut/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
22 |
--------------------------------------------------------------------------------
/sandboxes/doughnut/src/chartConfig.ts:
--------------------------------------------------------------------------------
1 | export const data = {
2 | labels: ['VueJs', 'EmberJs', 'ReactJs', 'AngularJs'],
3 | datasets: [
4 | {
5 | backgroundColor: ['#41B883', '#E46651', '#00D8FF', '#DD1B16'],
6 | data: [40, 20, 80, 10]
7 | }
8 | ]
9 | }
10 |
11 | export const options = {
12 | responsive: true,
13 | maintainAspectRatio: false
14 | }
15 |
--------------------------------------------------------------------------------
/sandboxes/doughnut/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import vue from '@vitejs/plugin-vue'
3 |
4 | export default defineConfig({
5 | plugins: [vue()]
6 | })
7 |
--------------------------------------------------------------------------------
/sandboxes/events/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/events/index.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import App from './src/App.vue'
3 |
4 | createApp(App).mount('#app')
5 |
--------------------------------------------------------------------------------
/sandboxes/events/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "vue": "^3.2.31",
9 | "vue-chartjs": "^5.0.0"
10 | },
11 | "devDependencies": {
12 | "@vitejs/plugin-vue": "^4.0.0",
13 | "typescript": "^4.9.3",
14 | "vite": "^4.0.0"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/sandboxes/events/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
90 |
--------------------------------------------------------------------------------
/sandboxes/events/src/chartConfig.ts:
--------------------------------------------------------------------------------
1 | export const data = {
2 | labels: [
3 | 'January',
4 | 'February',
5 | 'March',
6 | 'April',
7 | 'May',
8 | 'June',
9 | 'July',
10 | 'August',
11 | 'September',
12 | 'October',
13 | 'November',
14 | 'December'
15 | ],
16 | datasets: [
17 | {
18 | label: 'Data One',
19 | backgroundColor: '#f87979',
20 | data: [40, 20, 12, 39, 10, 40, 39, 80, 40, 20, 12, 11]
21 | }
22 | ]
23 | }
24 |
25 | export const options = {
26 | responsive: true,
27 | maintainAspectRatio: false
28 | }
29 |
--------------------------------------------------------------------------------
/sandboxes/events/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import vue from '@vitejs/plugin-vue'
3 |
4 | export default defineConfig({
5 | plugins: [vue()]
6 | })
7 |
--------------------------------------------------------------------------------
/sandboxes/line/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/line/index.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import App from './src/App.vue'
3 |
4 | createApp(App).mount('#app')
5 |
--------------------------------------------------------------------------------
/sandboxes/line/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "vue": "^3.2.31",
9 | "vue-chartjs": "^5.0.0"
10 | },
11 | "devDependencies": {
12 | "@vitejs/plugin-vue": "^4.0.0",
13 | "typescript": "^4.9.3",
14 | "vite": "^4.0.0"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/sandboxes/line/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
39 |
--------------------------------------------------------------------------------
/sandboxes/line/src/chartConfig.ts:
--------------------------------------------------------------------------------
1 | export const data = {
2 | labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
3 | datasets: [
4 | {
5 | label: 'Data One',
6 | backgroundColor: '#f87979',
7 | data: [40, 39, 10, 40, 39, 80, 40]
8 | }
9 | ]
10 | }
11 |
12 | export const options = {
13 | responsive: true,
14 | maintainAspectRatio: false
15 | }
16 |
--------------------------------------------------------------------------------
/sandboxes/line/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import vue from '@vitejs/plugin-vue'
3 |
4 | export default defineConfig({
5 | plugins: [vue()]
6 | })
7 |
--------------------------------------------------------------------------------
/sandboxes/pie/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/pie/index.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import App from './src/App.vue'
3 |
4 | createApp(App).mount('#app')
5 |
--------------------------------------------------------------------------------
/sandboxes/pie/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "vue": "^3.2.31",
9 | "vue-chartjs": "^5.0.0"
10 | },
11 | "devDependencies": {
12 | "@vitejs/plugin-vue": "^4.0.0",
13 | "typescript": "^4.9.3",
14 | "vite": "^4.0.0"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/sandboxes/pie/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
22 |
--------------------------------------------------------------------------------
/sandboxes/pie/src/chartConfig.ts:
--------------------------------------------------------------------------------
1 | export const data = {
2 | labels: ['VueJs', 'EmberJs', 'ReactJs', 'AngularJs'],
3 | datasets: [
4 | {
5 | backgroundColor: ['#41B883', '#E46651', '#00D8FF', '#DD1B16'],
6 | data: [40, 20, 80, 10]
7 | }
8 | ]
9 | }
10 |
11 | export const options = {
12 | responsive: true,
13 | maintainAspectRatio: false
14 | }
15 |
--------------------------------------------------------------------------------
/sandboxes/pie/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import vue from '@vitejs/plugin-vue'
3 |
4 | export default defineConfig({
5 | plugins: [vue()]
6 | })
7 |
--------------------------------------------------------------------------------
/sandboxes/polar-area/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/polar-area/index.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import App from './src/App.vue'
3 |
4 | createApp(App).mount('#app')
5 |
--------------------------------------------------------------------------------
/sandboxes/polar-area/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "vue": "^3.2.31",
9 | "vue-chartjs": "^5.0.0"
10 | },
11 | "devDependencies": {
12 | "@vitejs/plugin-vue": "^4.0.0",
13 | "typescript": "^4.9.3",
14 | "vite": "^4.0.0"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/sandboxes/polar-area/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
28 |
--------------------------------------------------------------------------------
/sandboxes/polar-area/src/chartConfig.ts:
--------------------------------------------------------------------------------
1 | export const data = {
2 | labels: [
3 | 'Eating',
4 | 'Drinking',
5 | 'Sleeping',
6 | 'Designing',
7 | 'Coding',
8 | 'Cycling',
9 | 'Running'
10 | ],
11 | datasets: [
12 | {
13 | label: 'My First dataset',
14 | backgroundColor: 'rgba(179,181,198,0.2)',
15 | pointBackgroundColor: 'rgba(179,181,198,1)',
16 | pointBorderColor: '#fff',
17 | pointHoverBackgroundColor: '#fff',
18 | pointHoverBorderColor: 'rgba(179,181,198,1)',
19 | data: [65, 59, 90, 81, 56, 55, 40]
20 | },
21 | {
22 | label: 'My Second dataset',
23 | backgroundColor: 'rgba(255,99,132,0.2)',
24 | pointBackgroundColor: 'rgba(255,99,132,1)',
25 | pointBorderColor: '#fff',
26 | pointHoverBackgroundColor: '#fff',
27 | pointHoverBorderColor: 'rgba(255,99,132,1)',
28 | data: [28, 48, 40, 19, 96, 27, 100]
29 | }
30 | ]
31 | }
32 |
33 | export const options = {
34 | responsive: true,
35 | maintainAspectRatio: false
36 | }
37 |
--------------------------------------------------------------------------------
/sandboxes/polar-area/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import vue from '@vitejs/plugin-vue'
3 |
4 | export default defineConfig({
5 | plugins: [vue()]
6 | })
7 |
--------------------------------------------------------------------------------
/sandboxes/radar/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/radar/index.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import App from './src/App.vue'
3 |
4 | createApp(App).mount('#app')
5 |
--------------------------------------------------------------------------------
/sandboxes/radar/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "vue": "^3.2.31",
9 | "vue-chartjs": "^5.0.0"
10 | },
11 | "devDependencies": {
12 | "@vitejs/plugin-vue": "^4.0.0",
13 | "typescript": "^4.9.3",
14 | "vite": "^4.0.0"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/sandboxes/radar/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
37 |
--------------------------------------------------------------------------------
/sandboxes/radar/src/chartConfig.ts:
--------------------------------------------------------------------------------
1 | export const data = {
2 | labels: [
3 | 'Eating',
4 | 'Drinking',
5 | 'Sleeping',
6 | 'Designing',
7 | 'Coding',
8 | 'Cycling',
9 | 'Running'
10 | ],
11 | datasets: [
12 | {
13 | label: 'My First dataset',
14 | backgroundColor: 'rgba(179,181,198,0.2)',
15 | borderColor: 'rgba(179,181,198,1)',
16 | pointBackgroundColor: 'rgba(179,181,198,1)',
17 | pointBorderColor: '#fff',
18 | pointHoverBackgroundColor: '#fff',
19 | pointHoverBorderColor: 'rgba(179,181,198,1)',
20 | data: [65, 59, 90, 81, 56, 55, 40]
21 | },
22 | {
23 | label: 'My Second dataset',
24 | backgroundColor: 'rgba(255,99,132,0.2)',
25 | borderColor: 'rgba(255,99,132,1)',
26 | pointBackgroundColor: 'rgba(255,99,132,1)',
27 | pointBorderColor: '#fff',
28 | pointHoverBackgroundColor: '#fff',
29 | pointHoverBorderColor: 'rgba(255,99,132,1)',
30 | data: [28, 48, 40, 19, 96, 27, 100]
31 | }
32 | ]
33 | }
34 |
35 | export const options = {
36 | responsive: true,
37 | maintainAspectRatio: false
38 | }
39 |
--------------------------------------------------------------------------------
/sandboxes/radar/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import vue from '@vitejs/plugin-vue'
3 |
4 | export default defineConfig({
5 | plugins: [vue()]
6 | })
7 |
--------------------------------------------------------------------------------
/sandboxes/reactive/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/reactive/index.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import App from './src/App.vue'
3 |
4 | createApp(App).mount('#app')
5 |
--------------------------------------------------------------------------------
/sandboxes/reactive/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "vue": "^3.2.31",
9 | "vue-chartjs": "^5.0.0"
10 | },
11 | "devDependencies": {
12 | "@vitejs/plugin-vue": "^4.0.0",
13 | "typescript": "^4.9.3",
14 | "vite": "^4.0.0"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/sandboxes/reactive/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
33 |
--------------------------------------------------------------------------------
/sandboxes/reactive/src/chartConfig.ts:
--------------------------------------------------------------------------------
1 | function getRandomInt() {
2 | return Math.floor(Math.random() * (50 - 5 + 1)) + 5
3 | }
4 |
5 | export const randomData = () => ({
6 | labels: [
7 | 'January' + getRandomInt(),
8 | 'February',
9 | 'March',
10 | 'April',
11 | 'May',
12 | 'June',
13 | 'July',
14 | 'August',
15 | 'September',
16 | 'October',
17 | 'November',
18 | 'December'
19 | ],
20 | datasets: [
21 | {
22 | label: 'Data One',
23 | backgroundColor: '#f87979',
24 | data: [
25 | getRandomInt(),
26 | getRandomInt(),
27 | getRandomInt(),
28 | getRandomInt(),
29 | getRandomInt(),
30 | getRandomInt(),
31 | getRandomInt(),
32 | getRandomInt(),
33 | getRandomInt(),
34 | getRandomInt(),
35 | getRandomInt(),
36 | getRandomInt()
37 | ]
38 | }
39 | ]
40 | })
41 |
42 | export const options = {
43 | responsive: true,
44 | maintainAspectRatio: false
45 | }
46 |
--------------------------------------------------------------------------------
/sandboxes/reactive/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import vue from '@vitejs/plugin-vue'
3 |
4 | export default defineConfig({
5 | plugins: [vue()]
6 | })
7 |
--------------------------------------------------------------------------------
/sandboxes/scatter/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/scatter/index.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import App from './src/App.vue'
3 |
4 | createApp(App).mount('#app')
5 |
--------------------------------------------------------------------------------
/sandboxes/scatter/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "vue": "^3.2.31",
9 | "vue-chartjs": "^5.0.0"
10 | },
11 | "devDependencies": {
12 | "@vitejs/plugin-vue": "^4.0.0",
13 | "typescript": "^4.9.3",
14 | "vite": "^4.0.0"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/sandboxes/scatter/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
29 |
--------------------------------------------------------------------------------
/sandboxes/scatter/src/chartConfig.ts:
--------------------------------------------------------------------------------
1 | export const data = {
2 | datasets: [
3 | {
4 | label: 'Scatter Dataset 1',
5 | fill: false,
6 | borderColor: '#f87979',
7 | backgroundColor: '#f87979',
8 | data: [
9 | {
10 | x: -2,
11 | y: 4
12 | },
13 | {
14 | x: -1,
15 | y: 1
16 | },
17 | {
18 | x: 0,
19 | y: 0
20 | },
21 | {
22 | x: 1,
23 | y: 1
24 | },
25 | {
26 | x: 2,
27 | y: 4
28 | }
29 | ]
30 | },
31 | {
32 | label: 'Scatter Dataset 2',
33 | fill: false,
34 | borderColor: '#7acbf9',
35 | backgroundColor: '#7acbf9',
36 | data: [
37 | {
38 | x: -2,
39 | y: -4
40 | },
41 | {
42 | x: -1,
43 | y: -1
44 | },
45 | {
46 | x: 0,
47 | y: 1
48 | },
49 | {
50 | x: 1,
51 | y: -1
52 | },
53 | {
54 | x: 2,
55 | y: -4
56 | }
57 | ]
58 | }
59 | ]
60 | }
61 |
62 | export const options = {
63 | responsive: true,
64 | maintainAspectRatio: false
65 | }
66 |
--------------------------------------------------------------------------------
/sandboxes/scatter/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import vue from '@vitejs/plugin-vue'
3 |
4 | export default defineConfig({
5 | plugins: [vue()]
6 | })
7 |
--------------------------------------------------------------------------------
/sandboxes/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "baseUrl": ".",
5 | "paths": {
6 | "vue-chartjs": ["../src"]
7 | }
8 | },
9 | "include": ["."]
10 | }
11 |
--------------------------------------------------------------------------------
/src/chart.ts:
--------------------------------------------------------------------------------
1 | import { Chart as ChartJS } from 'chart.js'
2 | import {
3 | defineComponent,
4 | h,
5 | nextTick,
6 | onBeforeUnmount,
7 | onMounted,
8 | ref,
9 | shallowRef,
10 | toRaw,
11 | watch
12 | } from 'vue'
13 |
14 | import type { ChartComponent } from './types.js'
15 | import { Props } from './props.js'
16 | import {
17 | cloneData,
18 | setLabels,
19 | setDatasets,
20 | setOptions,
21 | toRawIfProxy,
22 | cloneProxy
23 | } from './utils.js'
24 |
25 | export const Chart = defineComponent({
26 | // props: Props,
27 | setup(props, { expose, slots }) {
28 | const canvasRef = ref(null)
29 | const chartRef = shallowRef(null)
30 |
31 | expose({ chart: chartRef })
32 |
33 | const renderChart = () => {
34 | if (!canvasRef.value) return
35 |
36 | const { type, data, options, plugins, datasetIdKey } = props
37 | const clonedData = cloneData(data, datasetIdKey)
38 | const proxiedData = cloneProxy(clonedData, data)
39 |
40 | chartRef.value = new ChartJS(canvasRef.value, {
41 | type,
42 | data: proxiedData,
43 | options: { ...options },
44 | plugins
45 | })
46 | }
47 |
48 | const destroyChart = () => {
49 | const chart = toRaw(chartRef.value)
50 |
51 | if (chart) {
52 | chart.destroy()
53 | chartRef.value = null
54 | }
55 | }
56 |
57 | const update = (chart: ChartJS) => {
58 | chart.update(props.updateMode)
59 | }
60 |
61 | onMounted(renderChart)
62 |
63 | onBeforeUnmount(destroyChart)
64 |
65 | watch(
66 | [() => props.options, () => props.data],
67 | (
68 | [nextOptionsProxy, nextDataProxy],
69 | [prevOptionsProxy, prevDataProxy]
70 | ) => {
71 | const chart = toRaw(chartRef.value)
72 |
73 | if (!chart) {
74 | return
75 | }
76 |
77 | let shouldUpdate = false
78 |
79 | if (nextOptionsProxy) {
80 | const nextOptions = toRawIfProxy(nextOptionsProxy)
81 | const prevOptions = toRawIfProxy(prevOptionsProxy)
82 |
83 | if (nextOptions && nextOptions !== prevOptions) {
84 | setOptions(chart, nextOptions)
85 | shouldUpdate = true
86 | }
87 | }
88 |
89 | if (nextDataProxy) {
90 | const nextLabels = toRawIfProxy(nextDataProxy.labels)
91 | const prevLabels = toRawIfProxy(prevDataProxy.labels)
92 | const nextDatasets = toRawIfProxy(nextDataProxy.datasets)
93 | const prevDatasets = toRawIfProxy(prevDataProxy.datasets)
94 |
95 | if (nextLabels !== prevLabels) {
96 | setLabels(chart.config.data, nextLabels)
97 | shouldUpdate = true
98 | }
99 |
100 | if (nextDatasets && nextDatasets !== prevDatasets) {
101 | setDatasets(chart.config.data, nextDatasets, props.datasetIdKey)
102 | shouldUpdate = true
103 | }
104 | }
105 |
106 | if (shouldUpdate) {
107 | nextTick(() => {
108 | update(chart)
109 | })
110 | }
111 | },
112 | { deep: true }
113 | )
114 |
115 | return () => {
116 | return h(
117 | 'canvas',
118 | {
119 | role: 'img',
120 | ariaLabel: props.ariaLabel,
121 | ariaDescribedby: props.ariaDescribedby,
122 | ref: canvasRef
123 | },
124 | [h('p', {}, [slots.default ? slots.default() : ''])]
125 | )
126 | }
127 | }
128 | }) as ChartComponent
129 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import { Chart } from './chart.js'
2 | import {
3 | createTypedChart,
4 | Bar,
5 | Doughnut,
6 | Line,
7 | Pie,
8 | PolarArea,
9 | Radar,
10 | Bubble,
11 | Scatter
12 | } from './typedCharts.js'
13 |
14 | export type { ChartProps, ChartComponentRef } from './types.js'
15 | export {
16 | getDatasetAtEvent,
17 | getElementAtEvent,
18 | getElementsAtEvent
19 | } from './utils.js'
20 | export {
21 | Chart,
22 | createTypedChart,
23 | Bar,
24 | Doughnut,
25 | Line,
26 | Pie,
27 | PolarArea,
28 | Radar,
29 | Bubble,
30 | Scatter
31 | }
32 |
--------------------------------------------------------------------------------
/src/props.ts:
--------------------------------------------------------------------------------
1 | import type { PropType } from 'vue'
2 | import type {
3 | ChartType,
4 | ChartData,
5 | ChartOptions,
6 | Plugin,
7 | UpdateMode
8 | } from 'chart.js'
9 |
10 | export const CommonProps = {
11 | data: {
12 | type: Object as PropType,
13 | required: true
14 | },
15 | options: {
16 | type: Object as PropType,
17 | default: () => ({})
18 | },
19 | plugins: {
20 | type: Array as PropType,
21 | default: () => []
22 | },
23 | datasetIdKey: {
24 | type: String,
25 | default: 'label'
26 | },
27 | updateMode: {
28 | type: String as PropType,
29 | default: undefined
30 | }
31 | } as const
32 |
33 | export const A11yProps = {
34 | ariaLabel: {
35 | type: String
36 | },
37 | ariaDescribedby: {
38 | type: String
39 | }
40 | } as const
41 |
42 | export const Props = {
43 | type: {
44 | type: String as PropType,
45 | required: true
46 | },
47 | ...CommonProps,
48 | ...A11yProps
49 | } as const
50 |
--------------------------------------------------------------------------------
/src/typedCharts.ts:
--------------------------------------------------------------------------------
1 | import { defineComponent, shallowRef, h } from 'vue'
2 | import type { ChartType, ChartComponentLike, DefaultDataPoint } from 'chart.js'
3 | import {
4 | Chart as ChartJS,
5 | BarController,
6 | BubbleController,
7 | DoughnutController,
8 | LineController,
9 | PieController,
10 | PolarAreaController,
11 | RadarController,
12 | ScatterController
13 | } from 'chart.js'
14 | import type { TypedChartComponent, ChartComponentRef } from './types.js'
15 | import { CommonProps } from './props.js'
16 | import { Chart } from './chart.js'
17 | import { compatProps } from './utils.js'
18 |
19 | export function createTypedChart<
20 | TType extends ChartType = ChartType,
21 | TData = DefaultDataPoint,
22 | TLabel = unknown
23 | >(
24 | type: TType,
25 | registerables: ChartComponentLike
26 | ): TypedChartComponent {
27 | ChartJS.register(registerables)
28 |
29 | return defineComponent({
30 | props: CommonProps,
31 | setup(props, { expose }) {
32 | const ref = shallowRef(null)
33 | const reforwardRef = (chartRef: ChartComponentRef) => {
34 | ref.value = chartRef?.chart
35 | }
36 |
37 | expose({ chart: ref })
38 |
39 | return () => {
40 | return h(
41 | Chart,
42 | compatProps(
43 | {
44 | ref: reforwardRef as any
45 | },
46 | {
47 | type,
48 | ...props
49 | }
50 | )
51 | )
52 | }
53 | }
54 | }) as any
55 | }
56 |
57 | export const Bar = /* #__PURE__ */ createTypedChart('bar', BarController)
58 |
59 | export const Doughnut = /* #__PURE__ */ createTypedChart(
60 | 'doughnut',
61 | DoughnutController
62 | )
63 |
64 | export const Line = /* #__PURE__ */ createTypedChart('line', LineController)
65 |
66 | export const Pie = /* #__PURE__ */ createTypedChart('pie', PieController)
67 |
68 | export const PolarArea = /* #__PURE__ */ createTypedChart(
69 | 'polarArea',
70 | PolarAreaController
71 | )
72 |
73 | export const Radar = /* #__PURE__ */ createTypedChart('radar', RadarController)
74 |
75 | export const Bubble = /* #__PURE__ */ createTypedChart(
76 | 'bubble',
77 | BubbleController
78 | )
79 |
80 | export const Scatter = /* #__PURE__ */ createTypedChart(
81 | 'scatter',
82 | ScatterController
83 | )
84 |
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
1 | import type { DefineComponent } from 'vue'
2 | import type {
3 | Chart as ChartJS,
4 | ChartType,
5 | ChartData,
6 | ChartOptions,
7 | DefaultDataPoint,
8 | Plugin,
9 | UpdateMode
10 | } from 'chart.js'
11 |
12 | export interface ChartProps<
13 | TType extends ChartType = ChartType,
14 | TData = DefaultDataPoint,
15 | TLabel = unknown
16 | > {
17 | /**
18 | * Chart.js chart type
19 | */
20 | type: TType
21 | /**
22 | * The data object that is passed into the Chart.js chart
23 | * @see https://www.chartjs.org/docs/latest/getting-started/
24 | */
25 | data: ChartData
26 | /**
27 | * The options object that is passed into the Chart.js chart
28 | * @see https://www.chartjs.org/docs/latest/general/options.html
29 | * @default {}
30 | */
31 | options?: ChartOptions
32 | /**
33 | * The plugins array that is passed into the Chart.js chart
34 | * @see https://www.chartjs.org/docs/latest/developers/plugins.html
35 | * @default []
36 | */
37 | plugins?: Plugin[]
38 | /**
39 | * Key name to identificate dataset
40 | * @default 'label'
41 | */
42 | datasetIdKey?: string
43 | /**
44 | * A mode string to indicate transition configuration should be used.
45 | * @see https://www.chartjs.org/docs/latest/developers/api.html#update-mode
46 | */
47 | updateMode?: UpdateMode
48 | }
49 |
50 | export interface ChartComponentRef<
51 | TType extends ChartType = ChartType,
52 | TData = DefaultDataPoint,
53 | TLabel = unknown
54 | > {
55 | chart: ChartJS | null
56 | }
57 |
58 | export type ChartComponent = DefineComponent
59 |
60 | export type TypedChartComponent<
61 | TType extends ChartType,
62 | TData = DefaultDataPoint,
63 | TLabel = unknown
64 | > = DefineComponent, 'type'>>
65 |
--------------------------------------------------------------------------------
/src/utils.ts:
--------------------------------------------------------------------------------
1 | import { isProxy, toRaw, version } from 'vue'
2 | import type {
3 | Chart,
4 | ChartType,
5 | ChartData,
6 | ChartDataset,
7 | ChartOptions,
8 | DefaultDataPoint
9 | } from 'chart.js'
10 |
11 | export const compatProps =
12 | version[0] === '2'
13 | ? (internals: I, props: T) =>
14 | Object.assign(internals, { attrs: props }) as unknown as I & T
15 | : (internals: I, props: T) =>
16 | Object.assign(internals, props)
17 |
18 | export function toRawIfProxy(obj: T) {
19 | return isProxy(obj) ? toRaw(obj) : obj
20 | }
21 |
22 | export function cloneProxy(obj: T, src = obj) {
23 | return isProxy(src) ? new Proxy(obj, {}) : obj
24 | }
25 |
26 | export function setOptions<
27 | TType extends ChartType = ChartType,
28 | TData = DefaultDataPoint,
29 | TLabel = unknown
30 | >(chart: Chart, nextOptions: ChartOptions) {
31 | const options = chart.options
32 |
33 | if (options && nextOptions) {
34 | Object.assign(options, nextOptions)
35 | }
36 | }
37 |
38 | export function setLabels<
39 | TType extends ChartType = ChartType,
40 | TData = DefaultDataPoint,
41 | TLabel = unknown
42 | >(
43 | currentData: ChartData,
44 | nextLabels: TLabel[] | undefined
45 | ) {
46 | currentData.labels = nextLabels
47 | }
48 |
49 | export function setDatasets<
50 | TType extends ChartType = ChartType,
51 | TData = DefaultDataPoint,
52 | TLabel = unknown
53 | >(
54 | currentData: ChartData,
55 | nextDatasets: ChartDataset[],
56 | datasetIdKey: string
57 | ) {
58 | const addedDatasets: ChartDataset[] = []
59 |
60 | currentData.datasets = nextDatasets.map(
61 | (nextDataset: Record) => {
62 | // given the new set, find it's current match
63 | const currentDataset = currentData.datasets.find(
64 | (dataset: Record) =>
65 | dataset[datasetIdKey] === nextDataset[datasetIdKey]
66 | )
67 |
68 | // There is no original to update, so simply add new one
69 | if (
70 | !currentDataset ||
71 | !nextDataset.data ||
72 | addedDatasets.includes(currentDataset)
73 | ) {
74 | return { ...nextDataset } as ChartDataset
75 | }
76 |
77 | addedDatasets.push(currentDataset)
78 |
79 | Object.assign(currentDataset, nextDataset)
80 |
81 | return currentDataset
82 | }
83 | )
84 | }
85 |
86 | export function cloneData<
87 | TType extends ChartType = ChartType,
88 | TData = DefaultDataPoint,
89 | TLabel = unknown
90 | >(data: ChartData, datasetIdKey: string) {
91 | const nextData: ChartData = {
92 | labels: [],
93 | datasets: []
94 | }
95 |
96 | setLabels(nextData, data.labels)
97 | setDatasets(nextData, data.datasets, datasetIdKey)
98 |
99 | return nextData
100 | }
101 |
102 | /**
103 | * Get dataset from mouse click event
104 | * @param chart - Chart.js instance
105 | * @param event - Mouse click event
106 | * @returns Dataset
107 | */
108 | export function getDatasetAtEvent(chart: Chart, event: MouseEvent) {
109 | return chart.getElementsAtEventForMode(
110 | event,
111 | 'dataset',
112 | { intersect: true },
113 | false
114 | )
115 | }
116 |
117 | /**
118 | * Get single dataset element from mouse click event
119 | * @param chart - Chart.js instance
120 | * @param event - Mouse click event
121 | * @returns Dataset
122 | */
123 | export function getElementAtEvent(chart: Chart, event: MouseEvent) {
124 | return chart.getElementsAtEventForMode(
125 | event,
126 | 'nearest',
127 | { intersect: true },
128 | false
129 | )
130 | }
131 |
132 | /**
133 | * Get all dataset elements from mouse click event
134 | * @param chart - Chart.js instance
135 | * @param event - Mouse click event
136 | * @returns Dataset
137 | */
138 | export function getElementsAtEvent(chart: Chart, event: MouseEvent) {
139 | return chart.getElementsAtEventForMode(
140 | event,
141 | 'index',
142 | { intersect: true },
143 | false
144 | )
145 | }
146 |
--------------------------------------------------------------------------------
/stories/bar.stories.ts:
--------------------------------------------------------------------------------
1 | import 'chart.js/auto'
2 | import { Bar } from '../src/index.js'
3 | import * as barChartConfig from '../sandboxes/bar/src/chartConfig.js'
4 |
5 | export default {
6 | title: 'BarChart',
7 | component: Bar,
8 | parameters: {
9 | layout: 'centered'
10 | }
11 | }
12 |
13 | export function Default(args) {
14 | return {
15 | components: { Bar },
16 | template: ' ',
17 | setup() {
18 | return { args }
19 | }
20 | }
21 | }
22 |
23 | Default.args = {
24 | id: 'bar-chart',
25 | width: 400,
26 | height: 400,
27 | ...barChartConfig
28 | }
29 |
--------------------------------------------------------------------------------
/stories/bubble.stories.ts:
--------------------------------------------------------------------------------
1 | import 'chart.js/auto'
2 | import { Bubble } from '../src/index.js'
3 | import * as bubbleChartConfig from '../sandboxes/bubble/src/chartConfig.js'
4 |
5 | export default {
6 | title: 'BubbleChart',
7 | component: Bubble,
8 | parameters: {
9 | layout: 'centered'
10 | }
11 | }
12 |
13 | export function Default(args) {
14 | return {
15 | components: { Bubble },
16 | template: ' ',
17 | setup() {
18 | return { args }
19 | }
20 | }
21 | }
22 |
23 | Default.args = {
24 | id: 'bar-chart',
25 | width: 400,
26 | height: 400,
27 | ...bubbleChartConfig
28 | }
29 |
--------------------------------------------------------------------------------
/stories/chart.stories.ts:
--------------------------------------------------------------------------------
1 | import 'chart.js/auto'
2 | import type { InteractionItem } from 'chart.js'
3 | import { ref } from 'vue'
4 | import {
5 | ChartComponentRef,
6 | Chart,
7 | getDatasetAtEvent,
8 | getElementAtEvent,
9 | getElementsAtEvent
10 | } from '../src/index.js'
11 | import * as barChartConfig from '../sandboxes/bar/src/chartConfig.js'
12 |
13 | export default {
14 | title: 'Chart',
15 | component: Chart,
16 | parameters: {
17 | layout: 'centered'
18 | }
19 | }
20 |
21 | export function Default(args) {
22 | return {
23 | components: { Chart },
24 | template: ' ',
25 | setup() {
26 | return { args }
27 | }
28 | }
29 | }
30 |
31 | Default.args = {
32 | id: 'bar-chart',
33 | type: 'bar',
34 | width: 400,
35 | height: 400,
36 | ...barChartConfig
37 | }
38 |
39 | export function Events(args) {
40 | return {
41 | components: { Chart },
42 | template: ' ',
43 | setup() {
44 | const datasetAtEvent = (dataset: InteractionItem[]) => {
45 | if (!dataset.length) return
46 |
47 | const datasetIndex = dataset[0].datasetIndex
48 |
49 | console.log('dataset', barChartConfig.data.datasets[datasetIndex].label)
50 | }
51 |
52 | const elementAtEvent = (element: InteractionItem[]) => {
53 | if (!element.length) return
54 |
55 | const { datasetIndex, index } = element[0]
56 |
57 | console.log(
58 | 'element',
59 | barChartConfig.data.labels[index],
60 | barChartConfig.data.datasets[datasetIndex].data[index]
61 | )
62 | }
63 |
64 | const elementsAtEvent = (elements: InteractionItem[]) => {
65 | if (!elements.length) return
66 |
67 | console.log('elements', elements)
68 | }
69 |
70 | const chartRef = ref(null)
71 |
72 | const onClick = (event: MouseEvent) => {
73 | const {
74 | value: { chart }
75 | } = chartRef
76 |
77 | if (!chart) {
78 | return
79 | }
80 |
81 | datasetAtEvent(getDatasetAtEvent(chart, event))
82 | elementAtEvent(getElementAtEvent(chart, event))
83 | elementsAtEvent(getElementsAtEvent(chart, event))
84 | }
85 |
86 | return {
87 | chartRef,
88 | args,
89 | onClick
90 | }
91 | }
92 | }
93 | }
94 |
95 | Events.args = {
96 | id: 'bar-chart',
97 | type: 'bar',
98 | width: 400,
99 | height: 400,
100 | ...barChartConfig
101 | }
102 |
--------------------------------------------------------------------------------
/stories/custom.stories.ts:
--------------------------------------------------------------------------------
1 | import 'chart.js/auto'
2 | import LineWithLineChart from '../sandboxes/custom/src/components/LineWithLineChart.js'
3 | import * as customChartConfig from '../sandboxes/custom/src/chartConfig.js'
4 |
5 | export default {
6 | title: 'CustomChart',
7 | component: LineWithLineChart,
8 | parameters: {
9 | layout: 'centered'
10 | }
11 | }
12 |
13 | export function Default(args) {
14 | return {
15 | components: { LineWithLineChart },
16 | template: ' ',
17 | setup() {
18 | return { args }
19 | }
20 | }
21 | }
22 |
23 | Default.args = {
24 | id: 'custom-chart',
25 | width: 400,
26 | height: 400,
27 | ...customChartConfig
28 | }
29 |
--------------------------------------------------------------------------------
/stories/doughnut.stories.ts:
--------------------------------------------------------------------------------
1 | import 'chart.js/auto'
2 | import { Doughnut } from '../src/index.js'
3 | import * as doughnutChartConfig from '../sandboxes/doughnut/src/chartConfig.js'
4 |
5 | export default {
6 | title: 'DoughnutChart',
7 | component: Doughnut,
8 | parameters: {
9 | layout: 'centered'
10 | }
11 | }
12 |
13 | export function Default(args) {
14 | return {
15 | components: { Doughnut },
16 | template: ' ',
17 | setup() {
18 | return { args }
19 | }
20 | }
21 | }
22 |
23 | Default.args = {
24 | id: 'doughnut-chart',
25 | width: 400,
26 | height: 400,
27 | ...doughnutChartConfig
28 | }
29 |
--------------------------------------------------------------------------------
/stories/line.stories.ts:
--------------------------------------------------------------------------------
1 | import 'chart.js/auto'
2 | import { Line } from '../src/index.js'
3 | import * as lineChartConfig from '../sandboxes/line/src/chartConfig.js'
4 |
5 | export default {
6 | title: 'LineChart',
7 | component: Line,
8 | parameters: {
9 | layout: 'centered'
10 | }
11 | }
12 |
13 | export function Default(args) {
14 | return {
15 | components: { Line },
16 | template: ' ',
17 | setup() {
18 | return { args }
19 | }
20 | }
21 | }
22 |
23 | Default.args = {
24 | id: 'line-chart',
25 | width: 400,
26 | height: 400,
27 | ...lineChartConfig
28 | }
29 |
--------------------------------------------------------------------------------
/stories/pie.stories.ts:
--------------------------------------------------------------------------------
1 | import 'chart.js/auto'
2 | import { Pie } from '../src/index.js'
3 | import * as pieChartConfig from '../sandboxes/pie/src/chartConfig.js'
4 |
5 | export default {
6 | title: 'PieChart',
7 | component: Pie,
8 | parameters: {
9 | layout: 'centered'
10 | }
11 | }
12 |
13 | export function Default(args) {
14 | return {
15 | components: { Pie },
16 | template: ' ',
17 | setup() {
18 | return { args }
19 | }
20 | }
21 | }
22 |
23 | Default.args = {
24 | id: 'pie-chart',
25 | width: 400,
26 | height: 400,
27 | ...pieChartConfig
28 | }
29 |
--------------------------------------------------------------------------------
/stories/polarArea.stories.ts:
--------------------------------------------------------------------------------
1 | import 'chart.js/auto'
2 | import { PolarArea } from '../src/index.js'
3 | import * as polarAreaChartConfig from '../sandboxes/polar-area/src/chartConfig.js'
4 |
5 | export default {
6 | title: 'PolarAreaChart',
7 | component: PolarArea,
8 | parameters: {
9 | layout: 'centered'
10 | }
11 | }
12 |
13 | export function Default(args) {
14 | return {
15 | components: { PolarArea },
16 | template: ' ',
17 | setup() {
18 | return { args }
19 | }
20 | }
21 | }
22 |
23 | Default.args = {
24 | id: 'polar-area-chart',
25 | width: 400,
26 | height: 400,
27 | ...polarAreaChartConfig
28 | }
29 |
--------------------------------------------------------------------------------
/stories/radar.stories.ts:
--------------------------------------------------------------------------------
1 | import 'chart.js/auto'
2 | import { Radar } from '../src/index.js'
3 | import * as radarChartConfig from '../sandboxes/radar/src/chartConfig.js'
4 |
5 | export default {
6 | title: 'RadarChart',
7 | component: Radar,
8 | parameters: {
9 | layout: 'centered'
10 | }
11 | }
12 |
13 | export function Default(args) {
14 | return {
15 | components: { Radar },
16 | template: ' ',
17 | setup() {
18 | return { args }
19 | }
20 | }
21 | }
22 |
23 | Default.args = {
24 | id: 'radar-chart',
25 | width: 400,
26 | height: 400,
27 | ...radarChartConfig
28 | }
29 |
--------------------------------------------------------------------------------
/stories/reactive.stories.ts:
--------------------------------------------------------------------------------
1 | import 'chart.js/auto'
2 | import { ref, onMounted } from 'vue'
3 | import { Bar } from '../src/index.js'
4 | import * as reactiveChartConfig from '../sandboxes/reactive/src/chartConfig.js'
5 |
6 | export default {
7 | title: 'Reactive',
8 | component: Bar,
9 | parameters: {
10 | layout: 'centered'
11 | }
12 | }
13 |
14 | export function Default(args) {
15 | return {
16 | components: { Bar },
17 | template: ' ',
18 | setup() {
19 | const options = reactiveChartConfig.options
20 | const data = ref({
21 | datasets: []
22 | })
23 |
24 | onMounted(() => {
25 | setInterval(() => {
26 | data.value = reactiveChartConfig.randomData()
27 | }, 3000)
28 | })
29 |
30 | return {
31 | args,
32 | options,
33 | data
34 | }
35 | }
36 | }
37 | }
38 |
39 | Default.args = {
40 | id: 'reactive-chart',
41 | width: 400,
42 | height: 400
43 | }
44 |
--------------------------------------------------------------------------------
/stories/scatter.stories.ts:
--------------------------------------------------------------------------------
1 | import 'chart.js/auto'
2 | import { Scatter } from '../src/index.js'
3 | import * as scatterChartConfig from '../sandboxes/scatter/src/chartConfig.js'
4 |
5 | export default {
6 | title: 'ScatterChart',
7 | component: Scatter,
8 | parameters: {
9 | layout: 'centered'
10 | }
11 | }
12 |
13 | export function Default(args) {
14 | return {
15 | components: { Scatter },
16 | template: ' ',
17 | setup() {
18 | return { args }
19 | }
20 | }
21 | }
22 |
23 | Default.args = {
24 | id: 'scatter-chart',
25 | width: 400,
26 | height: 400,
27 | ...scatterChartConfig
28 | }
29 |
--------------------------------------------------------------------------------
/test/Bar.spec.ts:
--------------------------------------------------------------------------------
1 | import { describe, it, expect } from 'vitest'
2 | import { mount } from '@vue/test-utils'
3 | import { Bar } from '../src/index.js'
4 | import * as barChartConfig from '../sandboxes/bar/src/chartConfig.js'
5 |
6 | describe('BarChart', () => {
7 | it('should render a canvas', () => {
8 | const wrapper = mount(Bar, {
9 | props: barChartConfig as any
10 | })
11 |
12 | const canvas = wrapper.find('canvas')
13 |
14 | expect(canvas.exists()).toBe(true)
15 | expect(canvas.element.id).toBe('')
16 | })
17 |
18 | it('should change id based on prop', () => {
19 | const wrapper = mount(Bar, {
20 | props: {
21 | id: 'bar-chart-id',
22 | ...barChartConfig
23 | } as any
24 | })
25 |
26 | const canvas = wrapper.find('canvas')
27 |
28 | expect(canvas.exists()).toBe(true)
29 | expect(canvas.element.id).toBe('bar-chart-id')
30 | })
31 |
32 | it('should add inline plugins based on prop', () => {
33 | const testPlugin = {
34 | id: 'test'
35 | }
36 |
37 | const wrapper = mount(Bar, {
38 | props: {
39 | plugins: [testPlugin],
40 | ...barChartConfig
41 | } as any
42 | })
43 |
44 | expect(wrapper.props().plugins.length).toEqual(1)
45 | })
46 | })
47 |
--------------------------------------------------------------------------------
/test/Bubble.spec.ts:
--------------------------------------------------------------------------------
1 | import { describe, it, expect } from 'vitest'
2 | import { mount } from '@vue/test-utils'
3 | import { Bubble } from '../src/index.js'
4 | import * as bubbleChartConfig from '../sandboxes/bubble/src/chartConfig.js'
5 |
6 | describe('BubbleChart', () => {
7 | it('should render a canvas', () => {
8 | const wrapper = mount(Bubble, {
9 | props: bubbleChartConfig as any
10 | })
11 |
12 | const canvas = wrapper.find('canvas')
13 |
14 | expect(canvas.exists()).toBe(true)
15 | expect(canvas.element.id).toBe('')
16 | })
17 |
18 | it('should change id based on prop', () => {
19 | const wrapper = mount(Bubble, {
20 | props: {
21 | id: 'bubble-chart-id',
22 | ...bubbleChartConfig
23 | } as any
24 | })
25 |
26 | const canvas = wrapper.find('canvas')
27 |
28 | expect(canvas.exists()).toBe(true)
29 | expect(canvas.element.id).toBe('bubble-chart-id')
30 | })
31 |
32 | it('should add inline plugins based on prop', () => {
33 | const testPlugin = {
34 | id: 'test'
35 | }
36 |
37 | const wrapper = mount(Bubble, {
38 | props: {
39 | plugins: [testPlugin],
40 | ...bubbleChartConfig
41 | } as any
42 | })
43 |
44 | expect(wrapper.props().plugins.length).toEqual(1)
45 | })
46 | })
47 |
--------------------------------------------------------------------------------
/test/Doughnut.spec.ts:
--------------------------------------------------------------------------------
1 | import { describe, it, expect } from 'vitest'
2 | import { mount } from '@vue/test-utils'
3 | import { Doughnut } from '../src/index.js'
4 | import * as doughnutChartConfig from '../sandboxes/doughnut/src/chartConfig.js'
5 |
6 | describe('DoughnutChart', () => {
7 | it('should render a canvas', () => {
8 | const wrapper = mount(Doughnut, {
9 | props: doughnutChartConfig as any
10 | })
11 |
12 | const canvas = wrapper.find('canvas')
13 |
14 | expect(canvas.exists()).toBe(true)
15 | expect(canvas.element.id).toBe('')
16 | })
17 |
18 | it('should change id based on prop', () => {
19 | const wrapper = mount(Doughnut, {
20 | props: {
21 | id: 'doughnut-chart-id',
22 | ...doughnutChartConfig
23 | } as any
24 | })
25 |
26 | const canvas = wrapper.find('canvas')
27 |
28 | expect(canvas.exists()).toBe(true)
29 | expect(canvas.element.id).toBe('doughnut-chart-id')
30 | })
31 |
32 | it('should add inline plugins based on prop', () => {
33 | const testPlugin = {
34 | id: 'test'
35 | }
36 |
37 | const wrapper = mount(Doughnut, {
38 | props: {
39 | plugins: [testPlugin],
40 | ...doughnutChartConfig
41 | } as any
42 | })
43 |
44 | expect(wrapper.props().plugins.length).toEqual(1)
45 | })
46 | })
47 |
--------------------------------------------------------------------------------
/test/Line.spec.ts:
--------------------------------------------------------------------------------
1 | import { describe, it, expect } from 'vitest'
2 | import { mount } from '@vue/test-utils'
3 | import { Line } from '../src/index.js'
4 | import * as lineChartConfig from '../sandboxes/line/src/chartConfig.js'
5 |
6 | describe('LineChart', () => {
7 | it('should render a canvas', () => {
8 | const wrapper = mount(Line, {
9 | props: lineChartConfig as any
10 | })
11 |
12 | const canvas = wrapper.find('canvas')
13 |
14 | expect(canvas.exists()).toBe(true)
15 | expect(canvas.element.id).toBe('')
16 | })
17 |
18 | it('should change id based on prop', () => {
19 | const wrapper = mount(Line, {
20 | props: {
21 | id: 'line-chart-id',
22 | ...lineChartConfig
23 | } as any
24 | })
25 |
26 | const canvas = wrapper.find('canvas')
27 |
28 | expect(canvas.exists()).toBe(true)
29 | expect(canvas.element.id).toBe('line-chart-id')
30 | })
31 |
32 | it('should add inline plugins based on prop', () => {
33 | const testPlugin = {
34 | id: 'test'
35 | }
36 |
37 | const wrapper = mount(Line, {
38 | props: {
39 | plugins: [testPlugin],
40 | ...lineChartConfig
41 | } as any
42 | })
43 |
44 | expect(wrapper.props().plugins.length).toEqual(1)
45 | })
46 | })
47 |
--------------------------------------------------------------------------------
/test/Pie.spec.ts:
--------------------------------------------------------------------------------
1 | import { describe, it, expect } from 'vitest'
2 | import { mount } from '@vue/test-utils'
3 | import { Pie } from '../src/index.js'
4 | import * as pieChartConfig from '../sandboxes/pie/src/chartConfig.js'
5 |
6 | describe('PieChart', () => {
7 | it('should render a canvas', () => {
8 | const wrapper = mount(Pie, {
9 | props: pieChartConfig as any
10 | })
11 |
12 | const canvas = wrapper.find('canvas')
13 |
14 | expect(canvas.exists()).toBe(true)
15 | expect(canvas.element.id).toBe('')
16 | })
17 |
18 | it('should change id based on prop', () => {
19 | const wrapper = mount(Pie, {
20 | props: {
21 | id: 'pie-chart-id',
22 | ...pieChartConfig
23 | } as any
24 | })
25 |
26 | const canvas = wrapper.find('canvas')
27 |
28 | expect(canvas.exists()).toBe(true)
29 | expect(canvas.element.id).toBe('pie-chart-id')
30 | })
31 |
32 | it('should add inline plugins based on prop', () => {
33 | const testPlugin = {
34 | id: 'test'
35 | }
36 |
37 | const wrapper = mount(Pie, {
38 | props: {
39 | plugins: [testPlugin],
40 | ...pieChartConfig
41 | } as any
42 | })
43 |
44 | expect(wrapper.props().plugins.length).toEqual(1)
45 | })
46 | })
47 |
--------------------------------------------------------------------------------
/test/PolarArea.spec.ts:
--------------------------------------------------------------------------------
1 | import { describe, it, expect } from 'vitest'
2 | import { mount } from '@vue/test-utils'
3 | import { PolarArea } from '../src/index.js'
4 | import * as polarAreaChartConfig from '../sandboxes/polar-area/src/chartConfig.js'
5 |
6 | describe('PolarAreaChart', () => {
7 | it('should render a canvas', () => {
8 | const wrapper = mount(PolarArea, {
9 | props: polarAreaChartConfig as any
10 | })
11 |
12 | const canvas = wrapper.find('canvas')
13 |
14 | expect(canvas.exists()).toBe(true)
15 | expect(canvas.element.id).toBe('')
16 | })
17 |
18 | it('should change id based on prop', () => {
19 | const wrapper = mount(PolarArea, {
20 | props: {
21 | id: 'polar-area-chart-id',
22 | ...polarAreaChartConfig
23 | } as any
24 | })
25 |
26 | const canvas = wrapper.find('canvas')
27 |
28 | expect(canvas.exists()).toBe(true)
29 | expect(canvas.element.id).toBe('polar-area-chart-id')
30 | })
31 |
32 | it('should add inline plugins based on prop', () => {
33 | const testPlugin = {
34 | id: 'test'
35 | }
36 |
37 | const wrapper = mount(PolarArea, {
38 | props: {
39 | plugins: [testPlugin],
40 | ...polarAreaChartConfig
41 | } as any
42 | })
43 |
44 | expect(wrapper.props().plugins.length).toEqual(1)
45 | })
46 | })
47 |
--------------------------------------------------------------------------------
/test/Radar.spec.ts:
--------------------------------------------------------------------------------
1 | import { describe, it, expect } from 'vitest'
2 | import { mount } from '@vue/test-utils'
3 | import { Radar } from '../src/index.js'
4 | import * as radarChartConfig from '../sandboxes/radar/src/chartConfig.js'
5 |
6 | describe('RadarChart', () => {
7 | it('should render a canvas', () => {
8 | const wrapper = mount(Radar, {
9 | props: radarChartConfig as any
10 | })
11 |
12 | const canvas = wrapper.find('canvas')
13 |
14 | expect(canvas.exists()).toBe(true)
15 | expect(canvas.element.id).toBe('')
16 | })
17 |
18 | it('should change id based on prop', () => {
19 | const wrapper = mount(Radar, {
20 | props: {
21 | id: 'radar-chart-id',
22 | ...radarChartConfig
23 | } as any
24 | })
25 |
26 | const canvas = wrapper.find('canvas')
27 |
28 | expect(canvas.exists()).toBe(true)
29 | expect(canvas.element.id).toBe('radar-chart-id')
30 | })
31 |
32 | it('should add inline plugins based on prop', () => {
33 | const testPlugin = {
34 | id: 'test'
35 | }
36 |
37 | const wrapper = mount(Radar, {
38 | props: {
39 | plugins: [testPlugin],
40 | ...radarChartConfig
41 | } as any
42 | })
43 |
44 | expect(wrapper.props().plugins.length).toEqual(1)
45 | })
46 | })
47 |
--------------------------------------------------------------------------------
/test/Scatter.spec.ts:
--------------------------------------------------------------------------------
1 | import { describe, it, expect } from 'vitest'
2 | import { mount } from '@vue/test-utils'
3 | import { Scatter } from '../src/index.js'
4 | import * as scatterChartConfig from '../sandboxes/scatter/src/chartConfig.js'
5 |
6 | describe('ScatterChart', () => {
7 | it('should render a canvas', () => {
8 | const wrapper = mount(Scatter, {
9 | props: scatterChartConfig as any
10 | })
11 |
12 | const canvas = wrapper.find('canvas')
13 |
14 | expect(canvas.exists()).toBe(true)
15 | expect(canvas.element.id).toBe('')
16 | })
17 |
18 | it('should change id based on prop', () => {
19 | const wrapper = mount(Scatter, {
20 | props: {
21 | id: 'scatter-chart-id',
22 | ...scatterChartConfig
23 | } as any
24 | })
25 |
26 | const canvas = wrapper.find('canvas')
27 |
28 | expect(canvas.exists()).toBe(true)
29 | expect(canvas.element.id).toBe('scatter-chart-id')
30 | })
31 |
32 | it('should add inline plugins based on prop', () => {
33 | const testPlugin = {
34 | id: 'test'
35 | }
36 |
37 | const wrapper = mount(Scatter, {
38 | props: {
39 | plugins: [testPlugin],
40 | ...scatterChartConfig
41 | } as any
42 | })
43 |
44 | expect(wrapper.props().plugins.length).toEqual(1)
45 | })
46 | })
47 |
--------------------------------------------------------------------------------
/test/setup.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import 'vitest-canvas-mock'
3 |
4 | class ResizeObserver {
5 | observe() {}
6 | unobserve() {}
7 | disconnect() {}
8 | }
9 |
10 | window.ResizeObserver = ResizeObserver
11 |
12 | class MutationObserver {
13 | disconnect() {}
14 | unobserve() {}
15 | observe() {}
16 | }
17 |
18 | window.MutationObserver = MutationObserver
19 |
--------------------------------------------------------------------------------
/test/types.test-d.ts:
--------------------------------------------------------------------------------
1 | import { h } from 'vue'
2 | import { expectError } from 'tsd'
3 | import type { Plugin } from 'chart.js'
4 |
5 | import { Bar, Radar, Scatter, Doughnut } from '../src/index.js'
6 |
7 | const data = {
8 | datasets: []
9 | }
10 |
11 | const testPlugin = {
12 | id: 'test'
13 | }
14 |
15 | /**
16 | * Should check type-specific props
17 | */
18 |
19 | h(Radar, {
20 | data,
21 | plugins: []
22 | })
23 |
24 | h(Scatter, {
25 | data,
26 | plugins: []
27 | })
28 |
29 | h(Bar, {
30 | data,
31 | options: {}
32 | })
33 |
34 | expectError(
35 | h(Scatter, {
36 | data,
37 | plugins: [testPlugin] as Plugin<'bubble'>[]
38 | })
39 | )
40 |
41 | /**
42 | * Should check type-specific options
43 | */
44 |
45 | h(Doughnut, {
46 | data,
47 | options: {
48 | cutout: '75%'
49 | }
50 | })
51 |
52 | expectError(
53 | h(Scatter, {
54 | data,
55 | options: {
56 | cutout: '75%'
57 | }
58 | })
59 | )
60 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Type Checking */
4 | "strict": true,
5 | "strictBindCallApply": true,
6 | "noFallthroughCasesInSwitch": true,
7 | "noImplicitOverride": true,
8 | "noImplicitReturns": true,
9 | "noUnusedLocals": true,
10 | "noUnusedParameters": true,
11 | /* Modules */
12 | "baseUrl": ".",
13 | "module": "ESNext",
14 | "moduleResolution": "Node", // restore to "NodeNext" after Chart.js update
15 | "resolveJsonModule": true,
16 | /* Emit */
17 | "declaration": true,
18 | "declarationMap": true,
19 | "importsNotUsedAsValues": "error",
20 | "inlineSourceMap": true,
21 | "outDir": "dist",
22 | /* Interop Constraints */
23 | "allowSyntheticDefaultImports": true,
24 | "isolatedModules": true,
25 | /* Language and Environment */
26 | "lib": [
27 | "dom",
28 | "esnext"
29 | ],
30 | "target": "ESNext",
31 | /* Completeness */
32 | "skipLibCheck": true
33 | },
34 | "include": [
35 | "src"
36 | ],
37 | "exclude": [
38 | "dist"
39 | ]
40 | }
41 |
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import vue from '@vitejs/plugin-vue'
3 |
4 | export default defineConfig({
5 | plugins: [vue()],
6 | test: {
7 | environment: 'jsdom',
8 | setupFiles: ['test/setup.js'],
9 | deps: {
10 | inline: ['vitest-canvas-mock']
11 | },
12 | coverage: {
13 | reporter: ['lcovonly', 'text']
14 | }
15 | }
16 | })
17 |
--------------------------------------------------------------------------------
/website/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "website",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "vitepress dev src",
7 | "build": "vitepress build src"
8 | },
9 | "devDependencies": {
10 | "vitepress": "^0.22.3"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/website/src/.vitepress/config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vitepress'
2 |
3 | export default defineConfig({
4 | lastUpdated: true,
5 |
6 | themeConfig: {
7 | repo: 'apertureless/vue-chartjs',
8 | docsDir: 'website/src',
9 | docsBranch: 'main',
10 | editLinks: true,
11 | editLinkText: 'Help us improve this page!',
12 | lastUpdated: 'Last Updated',
13 |
14 | algolia: {
15 | indexName: 'vue-chartjs',
16 | apiKey: 'a1bb4528e8ed1eb89e40d6e4c1000514',
17 | appId: '24VA3R3NCC'
18 | },
19 |
20 | nav: [
21 | { text: 'Guide', link: '/guide/', activeMatch: '^/guide/' },
22 | {
23 | text: 'Migration guides',
24 | link: '/migration-guides/',
25 | activeMatch: '^/migration-guides/'
26 | },
27 | {
28 | text: 'API',
29 | link: '/api/',
30 | activeMatch: '^/api/'
31 | },
32 | {
33 | text: 'Examples',
34 | link: '/examples/',
35 | activeMatch: '^/examples/'
36 | },
37 | {
38 | text: 'Stack Overflow',
39 | link: 'https://stackoverflow.com/questions/tagged/vue-chartjs/'
40 | }
41 | ],
42 |
43 | sidebar: 'auto',
44 |
45 | locales: {
46 | '/': {
47 | selectText: 'Languages',
48 | label: 'English',
49 | editLinkText: 'Edit this page on GitHub'
50 | }
51 | // '/ru/': {
52 | // selectText: 'Языки',
53 | // label: 'Русский',
54 | // editLinkText: 'Редактировать эту страницу на GitHub',
55 | // nav: [
56 | // {
57 | // text: 'Руководство',
58 | // link: '/ru/guide/'
59 | // },
60 | // {
61 | // text: 'API',
62 | // link: '/ru/api/'
63 | // }
64 | // ]
65 | // }
66 | // '/zh-cn/': {
67 | // selectText: '选择语言',
68 | // label: '中文(简体)',
69 | // sidebar: 'auto',
70 | // editLinkText: '在GitHub上编辑本页',
71 | // nav: [
72 | // {
73 | // text: '指南',
74 | // link: '/zh-cn/guide/'
75 | // },
76 | // {
77 | // text: 'API 参考',
78 | // link: '/zh-cn/api/'
79 | // }
80 | // ]
81 | // },
82 | // '/ja/': {
83 | // selectText: 'Languages',
84 | // label: '日本語',
85 | // editLinkText: 'Edit this page on GitHub',
86 | // nav: [
87 | // {
88 | // text: 'Guide',
89 | // link: '/ja/guide/'
90 | // },
91 | // {
92 | // text: 'API',
93 | // link: '/ja/api/'
94 | // }
95 | // ]
96 | // },
97 | // '/pt-br/': {
98 | // selectText: 'Linguas',
99 | // label: 'Português do Brasil',
100 | // editLinkText: 'Edite esta página no GitHub',
101 | // nav: [
102 | // { text: 'Guia', link: '/pt-br/guide/' },
103 | // { text: 'API', link: '/pt-br/api/' }
104 | // ]
105 | // }
106 | }
107 | },
108 | locales: {
109 | '/': {
110 | lang: 'en-US',
111 | title: '📈 vue-chartjs',
112 | description: '⚡ Easy and beautiful charts with Chart.js and Vue.js'
113 | }
114 | // '/ru/': {
115 | // lang: 'ru',
116 | // title: '📈 vue-chartjs',
117 | // description: '⚡ Простые и красивые графики с Chart.js и Vue.js'
118 | // }
119 | // '/zh-cn/': {
120 | // lang: 'zh-CN',
121 | // title: '📈 vue-chartjs',
122 | // description: '⚡ 使用 Chart.js 和 Vue.js 搭建简单和漂亮的图表'
123 | // },
124 | // '/ja/': {
125 | // lang: 'ja',
126 | // title: '📈 vue-chartjs',
127 | // description: '⚡ Easy and beautiful charts with Chart.js and Vue.js'
128 | // },
129 | // '/pt-br/': {
130 | // lang: 'pt-br',
131 | // title: '📈 vue-chartjs',
132 | // description: '⚡ Gráficos bonitos e fácil com Chart.js e Vue.js'
133 | // }
134 | }
135 | })
136 |
--------------------------------------------------------------------------------
/website/src/CNAME:
--------------------------------------------------------------------------------
1 | vue-chartjs.org
2 |
--------------------------------------------------------------------------------
/website/src/api/index.md:
--------------------------------------------------------------------------------
1 | # Coding Reference
2 |
3 | ## Props
4 |
5 | Some basic props are defined in the components provided by `vue-chartjs`.
6 |
7 | | Prop | Description |
8 | |---|---|
9 | | data | Data object that is passed into the Chart.js chart |
10 | | options | Options object that is passed into the Chart.js chart |
11 | | datasetIdKey | Key name to identify the dataset |
12 | | plugins | Plugins array that is passed into the Chart.js chart |
13 | | updateMode | Mode string to indicate the transition configuration to be used. |
14 | | ariaLabel | An [ARIA label](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label) that describes the chart to make it accessible. |
15 | | ariaDescribedby | A reference to the [describing element](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-describedby). E. g. a table representation of the data. |
16 |
17 | The rest of the props will fall through to the canvas element.
18 |
19 | ## Global Methods
20 |
21 | Global Methods need to be imported.
22 |
23 | ### createTypedChart
24 |
25 | - **Type:** `Function`
26 | - **Arguments**:`chart-type`, `chart-controller`
27 | - **Usage:**
28 |
29 | ```js
30 | import { createTypedChart } from 'vue-chartjs'
31 | import { LineController } from 'chart.js'
32 |
33 | const CustomLine = createTypedChart('line', LineController)
34 | ```
35 |
--------------------------------------------------------------------------------
/website/src/examples/index.md:
--------------------------------------------------------------------------------
1 | # Examples
2 |
3 | ## Vue 3 charts
4 |
5 | - [Bar](https://stackblitz.com/github/apertureless/vue-chartjs/tree/main/sandboxes/bar)
6 | - [Bubble](https://stackblitz.com/github/apertureless/vue-chartjs/tree/main/sandboxes/bubble)
7 | - [Doughnut](https://stackblitz.com/github/apertureless/vue-chartjs/tree/main/sandboxes/doughnut)
8 | - [Line](https://stackblitz.com/github/apertureless/vue-chartjs/tree/main/sandboxes/line)
9 | - [Pie](https://stackblitz.com/github/apertureless/vue-chartjs/tree/main/sandboxes/pie)
10 | - [PolarArea](https://stackblitz.com/github/apertureless/vue-chartjs/tree/main/sandboxes/polar-area)
11 | - [Radar](https://stackblitz.com/github/apertureless/vue-chartjs/tree/main/sandboxes/radar)
12 | - [Scatter](https://stackblitz.com/github/apertureless/vue-chartjs/tree/main/sandboxes/scatter)
13 | - [Bar with reactive data](https://stackblitz.com/github/apertureless/vue-chartjs/tree/main/sandboxes/reactive)
14 | - [Custom chart](https://stackblitz.com/github/apertureless/vue-chartjs/tree/main/sandboxes/custom)
15 | - [Events](https://stackblitz.com/github/apertureless/vue-chartjs/tree/main/sandboxes/events)
16 |
17 | ## Vue 2 charts (vue-chartjs v4)
18 |
19 | - [Bar](https://codesandbox.io/s/github/apertureless/vue-chartjs/tree/v4/legacy/sandboxes/bar)
20 | - [Bubble](https://codesandbox.io/s/github/apertureless/vue-chartjs/tree/v4/legacy/sandboxes/bubble)
21 | - [Doughnut](https://codesandbox.io/s/github/apertureless/vue-chartjs/tree/v4/legacy/sandboxes/doughnut)
22 | - [Line](https://codesandbox.io/s/github/apertureless/vue-chartjs/tree/v4/legacy/sandboxes/line)
23 | - [Pie](https://codesandbox.io/s/github/apertureless/vue-chartjs/tree/v4/legacy/sandboxes/pie)
24 | - [PolarArea](https://codesandbox.io/s/github/apertureless/vue-chartjs/tree/v4/legacy/sandboxes/polar-area)
25 | - [Radar](https://codesandbox.io/s/github/apertureless/vue-chartjs/tree/v4/legacy/sandboxes/radar)
26 | - [Scatter](https://codesandbox.io/s/github/apertureless/vue-chartjs/tree/v4/legacy/sandboxes/scatter)
27 |
--------------------------------------------------------------------------------
/website/src/guide/index.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | **vue-chartjs** is a wrapper for [Chart.js](https://github.com/chartjs/Chart.js) in Vue. You can easily create reuseable chart components.
4 |
5 | Supports Chart.js v4.
6 |
7 | ## Introduction
8 |
9 | `vue-chartjs` lets you use Chart.js without much hassle inside Vue. It's perfect for people who need simple charts up and running as fast as possible.
10 |
11 | It abstracts the basic logic but exposes the Chart.js object to give you maximal flexibility.
12 |
13 | :::tip Need an API to fetch data?
14 | Please consider [Cube](https://cube.dev/?ref=eco-vue-chartjs), an open-source API for data apps.
15 | :::
16 |
17 | ## Installation
18 |
19 | You can install `vue-chartjs` over `yarn` or `npm` or `pnpm`. However, you also need to add `chart.js` as a dependency to your project because `Chart.js` is a peerDependency. This way you can have full control over the versioning of `Chart.js`.
20 |
21 | ```bash
22 | pnpm add vue-chartjs chart.js
23 | # or
24 | yarn add vue-chartjs chart.js
25 | # or
26 | npm i vue-chartjs chart.js
27 | ```
28 |
29 | ## Integration
30 |
31 | Every chart type that is available in Chart.js is exported as a named component and can be imported as such. These components are normal Vue components.
32 |
33 | The idea behind vue-chartjs is to provide easy-to-use components, with maximal flexibility and extensibility.
34 |
35 | ## Creating your first Chart
36 |
37 | First, you need to import the base chart.
38 |
39 | ```javascript
40 | import { Bar } from 'vue-chartjs'
41 | ```
42 |
43 | Check out the official [Chart.js docs](http://www.chartjs.org/docs/latest/#creating-a-chart) to see the object structure you need to provide.
44 |
45 | Just create your own component.
46 |
47 | **BarChart.vue**
48 |
49 | ```vue
50 |
51 |
56 |
57 |
58 |
80 | ```
81 |
82 | Use it in your vue app:
83 |
84 | **App.vue**
85 |
86 | ```vue
87 |
88 |
89 |
90 |
91 |
99 | ```
100 |
101 | ## Updating Charts
102 |
103 | Since v4 charts have data change watcher and options change watcher by default. Wrapper will update or re-render the chart if new data or new options is passed. Mixins have been removed.
104 |
105 | ```vue
106 |
107 |
108 |
109 |
110 |
126 | ```
127 |
128 | You may get Vue's `Target is readonly` warnings when you are updating your `chartData`.
129 |
130 | If your `chartData` is a `read-only` reactive value, you can override this warning by using a clone:
131 |
132 | ```vue
133 |
134 |
135 |
136 | ```
137 |
138 | Unless you have a writable computed `chartData`, you won't be able to use the newer `structuredClone`, as you'll likely hit the `Write operation failed: computed value is readonly` error.
139 |
140 | You don't need to use a clone if your `chartData` is a [writable computed value](https://vuejs.org/guide/essentials/computed#writable-computed).
141 |
142 |
143 |
144 | ## Access to Chart instance
145 |
146 | You can get access to chart instance via template refs.
147 |
148 | ```vue
149 |
150 |
151 |
152 | ```
153 |
154 | In Vue3 projects:
155 |
156 | ```javascript
157 | const chartInstance = this.$refs.bar.chart
158 | ```
159 |
160 | ## Accessibility
161 |
162 | To make your charts accessible to all users, you should label your charts.
163 | Please refer also to the official [Chart.js Accessibility notes](https://www.chartjs.org/docs/latest/general/accessibility.html).
164 |
165 | ### `aria-label`
166 |
167 | You can directly label a chart by passing an `aria-label` prop.
168 |
169 | ```vue
170 |
171 |
172 |
173 | ```
174 |
175 | ### `aria-describedby`
176 |
177 | You can reference to a describing element such as a table which describes the data by using the `aria-describedby` property.
178 |
179 | ```vue
180 |
181 |
182 |
183 | Sales figures for the years 2022 to 2024.
184 |
185 |
186 | 2022
187 | 2023
188 | 2024
189 |
190 |
191 |
192 |
193 | 987
194 | 1209
195 | 825
196 |
197 |
198 |
199 |
200 | ```
201 |
202 | ### Fallback-Content
203 |
204 | In case the Browser is not able to render the `canvas` element, you should consider providing fallback content by using the Slot of each component.
205 |
206 | ```vue
207 |
208 | Chart couldn't be loaded.
209 |
210 | ```
211 |
212 | ## Examples
213 |
214 | ### Chart with props
215 |
216 | Your goal should be to create reusable chart components. For this purpose, you should utilize Vue.js props to pass in chart options and chart data. This way, the parent component itself does not hold an opinion about fetching data and is only for presentation.
217 |
218 | ```vue
219 |
220 |
221 |
222 |
223 |
244 | ```
245 |
246 | ### Chart with local data
247 |
248 | You can handle your chart data directly in your parent component.
249 |
250 | ```vue
251 |
252 |
253 |
254 |
255 |
280 | ```
281 |
282 | ### Chart with API data
283 |
284 | A common pattern is to use an API to retrieve your data. However, there are some things to keep in mind. The most common problem is that you mount your chart component directly and pass in data from an asynchronous API call. The problem with this approach is that Chart.js tries to render your chart and access the chart data synchronously, so your chart mounts before the API data arrives.
285 |
286 | To prevent this, a simple `v-if` is the best solution.
287 |
288 | Create your chart component with a data prop and options prop, so we can pass in our data and options from a container component.
289 |
290 | ```vue
291 |
292 |
293 |
294 |
295 |
296 |
297 |
324 | ```
325 |
326 | ### Chart with dynamic styles
327 |
328 | You can set `responsive: true` and pass in a styles object which gets applied as inline styles to the outer ``. This way, you can change the height and width of the outer container dynamically, which is not the default behaviour of Chart.js. It is best to use computed properties for this.
329 |
330 | ::: warning
331 | You need to set `position: relative`
332 | :::
333 |
334 | ```vue
335 |
336 |
337 |
338 |
339 |
340 |
341 |
360 | ```
361 |
362 | ### Custom / New Charts
363 |
364 | Sometimes you need to extend the default Chart.js charts. There are a lot of [examples](http://www.chartjs.org/docs/latest/developers/charts.html) on how to extend and modify the default charts. Or, you can create your own chart type.
365 |
366 | In `vue-chartjs`, you can do this pretty much the same way:
367 |
368 | ```js
369 | // 1. Import Chart.js so you can use the global Chart object
370 | import { Chart } from 'chart.js'
371 | // 2. Import the `createTypedChart()` method to create the vue component.
372 | import { createTypedChart } from 'vue-chartjs'
373 | // 3. Import needed controller from Chart.js
374 | import { LineController } from 'chart.js'
375 |
376 | // 3. Extend one of the default charts
377 | // http://www.chartjs.org/docs/latest/developers/charts.html
378 | class LineWithLineController extends LineController { /* custom magic here */}
379 |
380 | // 4. Generate the vue-chartjs component
381 | // The first argument is the chart-id, the second the chart type, third is the custom controller
382 | const CustomLine = createTypedChart('line', LineWithLineController)
383 |
384 | // 5. Extend the CustomLine Component just like you do with the default vue-chartjs charts.
385 |
386 | export default {
387 | components: { CustomLine }
388 | }
389 | ```
390 |
391 | ## Resources
392 |
393 | Here are some resources, such as tutorials, on how to use `vue-chartjs`:
394 |
395 | - [Using vue-chartjs with WordPress](https://medium.com/@apertureless/wordpress-vue-and-chart-js-6b61493e289f)
396 | - [Create stunning Charts with Vue and Chart.js](https://hackernoon.com/creating-stunning-charts-with-vue-js-and-chart-js-28af584adc0a)
397 | - [Let’s Build a Web App with Vue, Chart.js and an API Part I](https://hackernoon.com/lets-build-a-web-app-with-vue-chart-js-and-an-api-544eb81c4b44)
398 | - [Let’s Build a Web App with Vue, Chart.js and an API Part II](https://hackernoon.com/lets-build-a-web-app-with-vue-chart-js-and-an-api-part-ii-39781b1d5acf)
399 | - [Build a realtime chart with VueJS and Pusher](https://blog.pusher.com/build-realtime-chart-with-vuejs-pusher/)
400 |
--------------------------------------------------------------------------------
/website/src/images/vue-chartjs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lu0415mc/vue-chartjs/d52075bdf18a718a2dc3dc220888198e46a81b67/website/src/images/vue-chartjs.png
--------------------------------------------------------------------------------
/website/src/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | home: true
3 | heroImage: https://raw.githubusercontent.com/apertureless/vue-chartjs/main/website/src/images/vue-chartjs.png
4 | actionText: Get Started →
5 | actionLink: /guide/
6 | features:
7 | - title: Easy
8 | details: Easy for both beginners and pros 🙌
9 | - title: Extendable
10 | details: Simple to use, easy to extend 💪
11 | - title: Powerful
12 | details: With the full power of chart.js 💯
13 | footer: MIT Licensed | Copyright © 2018-present Jakub Juszczak
14 | ---
15 |
--------------------------------------------------------------------------------
/website/src/ja/api/index.md:
--------------------------------------------------------------------------------
1 | # コーディング レファレンス
2 |
3 | ## Props
4 |
5 | `vue-chartjs`によって提供されるコンポーネントにはいくつかの基本的なプロパティが定義されています。 `拡張`しているので、それらは *見えない* ですが、それらの値は上書きすることができます:
6 |
7 | | Prop名 | 説明 |
8 | |---|---|
9 | | width | チャート幅 |
10 | | height | チャート高さ |
11 | | chart-id | canvas要素のid |
12 | | css-classes | 囲んでいる div の css クラス (文字列) |
13 | | styles | 囲んでいる div の css クラス (オブジェクト) |
14 | | plugins | chartjs プラグイン (配列) |
15 |
16 | ## Events
17 |
18 | `reactData`または` reactProp`ミックスインが使用されている場合、以下のイベントが発行されます。
19 |
20 | | Event名 | 説明|
21 | |---|---|
22 | | `chart:render` | ミックスインが完全にレンダリングしたとき |
23 | | `chart:destroy` | ミックスインがチャートオブジェクトインスタンスを削除したとき |
24 | | `chart:update` | ミックスインが再レンダリングの代わりに更新をしたとき |
25 | | `labels:update` | labelsがセットされたとき |
26 | | `xlabels:update` | xlabelsがセットされたとき |
27 | | `ylabels:update` | ylabelsがセットされたとき |
28 |
29 | ## Global Methods
30 | グローバルメソッドはインポートして使用します。
31 |
32 | ### generateChart
33 |
34 | - **Type:** `Function`
35 | - **Arguments**: `chart-id`, `chart-type`
36 | - **Usage:**
37 |
38 | ```js
39 | import { generateChart } from 'vue-chartjs'
40 | // First argument is the chart-id, second the chart type.
41 | const CustomLine = generateChart('custom-line', 'LineWithLine')
42 | ```
43 |
44 | ## Instance Methods
45 |
46 | インスタンスメソッドは独自のチャートコンポーネント内で使用することができます。
47 |
48 |
49 | ### generateLegend()
50 |
51 | HTMLの凡例を作成するヘルパー関数
52 |
53 | - **Type:** `Function`
54 | - **Arguments**: `none`
55 | - **Usage:**
56 |
57 | ```js {11}
58 | import { Line } from 'vue-chartjs'
59 |
60 | export default {
61 | extends: Line,
62 | props: ['datasets', 'options']
63 | data: () => ({
64 | htmlLegend: null
65 | })
66 | mounted () {
67 | this.renderChart(this.datasets, this.options)
68 | this.htmlLegend = this.generateLegend()
69 | }
70 | }
71 |
72 | ```
73 |
74 | ### プラグインの追加
75 |
76 | Chart.jsでは、グローバルプラグインとインラインプラグインを定義できます。 グローバルプラグインは、[Chart.js docs](http://www.chartjs.org/docs/latest/developers/plugins.html)で説明されているように`vue-chartjs`でも問題なく動作します。
77 |
78 |
79 | インラインプラグインを追加したい場合に備えて、`vue-chartjs`は`addPlugin()`と呼ばれるヘルパーメソッドを公開します。
80 |
81 | `renderChart()`メソッドの前に `addPlugin()`を呼び出すべきです。
82 |
83 | - **Type:** `Function`
84 | - **Arguments**: `Array` of Plugins
85 | - **Usage:**
86 |
87 | ```js
88 | mounted () {
89 | this.addPlugin({
90 | id: 'my-plugin',
91 | beforeInit: function (chart) {
92 | ....
93 | }
94 | })
95 | }
96 | ```
97 |
98 | ### renderChart()
99 |
100 | Chart.js のインスタンスを作成して描画します。
101 |
102 | - **Type:** `Function`
103 | - **Arguments**: `Chart Data`, `Chart Options`
104 | - **Usage:**
105 |
106 | ```js
107 | mounted () {
108 | this.renderChart({
109 | labels: ['January', 'February'],
110 | datasets: [
111 | {
112 | label: 'Data One',
113 | backgroundColor: '#f87979',
114 | data: [40, 20]
115 | }
116 | ]},
117 | {
118 | responsive: true
119 | }
120 | )
121 | }
122 | ```
123 |
124 | ## Chart.js オブジェクト
125 |
126 | 独自のチャートコンポーネント内からChart.jsのオブジェクトには `this.$data._chart` でアクセスできます。
127 |
128 | ## Canvas
129 |
130 | Canvas要素には `this.$refs.canvas` でアクセスできます。
131 |
--------------------------------------------------------------------------------
/website/src/ja/guide/index.md:
--------------------------------------------------------------------------------
1 | # 最初に
2 |
3 | **vue-chartjs** は [Chart.js](https://github.com/chartjs/Chart.js) をvueで使用するためのラッパーです。 再利用可能なチャートコンポーネントを簡単に作成できます。
4 |
5 | ## 初めに
6 |
7 | `vue-chartjs` あまり手間をかけずにvueの中でchart.jsを使うことができます。 シンプルなチャートをできるだけ早く起動して実行したいという人に最適です。
8 |
9 | chart.jsの基本ロジックを抽象化していますが、公開されたchart.jsのオブジェクトを使用して柔軟にカスタマイズできます。
10 |
11 | ## インストール
12 |
13 | ### NPM
14 |
15 | `npm`を使って` vue-chartjs`をインストールすることができます。 ただしプロジェクトへの依存関係として `chart.js`を追加する必要があります。 なぜなら `Chart.js`はpeerDependencyだからです。 このため、Chart.jsのバージョンを完全に制御できます。
16 |
17 | `yarn add vue-chartjs chart.js@2.9.4` or `npm install vue-chartjs chart.js@2.9.4 --save`
18 |
19 | ::: tip
20 | Vue.jsの Version 1.xを使用している場合は`legacy`タグを使用してください。しかし、vueのバージョン1はもうメンテナンスされません。
21 |
22 | `yarn add vue-chartjs@legacy`
23 | :::
24 |
25 | ### ブラウザ
26 |
27 | ブラウザから直接 `vue-chartjs` を使用することができます。
28 | 先に`Chart.js`スクリプトを追加してから`vue-chartjs`スクリプトを追加してください
29 |
30 | ```html
31 |
32 |
33 | ```
34 |
35 | ## 統合
36 |
37 | `Chart.js`で利用可能なすべてのチャートタイプは名前付きコンポーネントとしてエクスポートされ、そのままインポートすることができます。 これらのコンポーネントは通常のVueコンポーネントですが、それを`拡張`する必要があります。
38 |
39 | `vue-chartjs`の背後にある考え方は、最大限の柔軟性と拡張性を持ち、使いやすいコンポーネントを提供することです。 これを実現するには、独自の *Chart Component* を作成し、それを`vue-chartjs`コンポーネントして提供するように拡張する必要があります。
40 |
41 | 拡張することで、チャートコンポーネントのメソッドとロジックは、独自のチャートコンポーネントにマージされます。
42 |
43 | ## 最初のチャートの作成
44 |
45 | BaseChartをインポートしてextendします。この方法で異なるデータのチャートを表示するときに柔軟性が大幅に向上します。
46 | コンポーネントをカプセル化し、プロパティを使用してコンポーネント内のデータに渡したり、コンポーネント内に直接データを記述することができます。ただし直接コンポーネント内にデータを記述した場合は再利用ができません。
47 |
48 | パッケージ全体または各モジュールを個別にインポートできます。 インポートしたものを `extends:`か `mixins:[]`を使って指定します。 また `mounted()`フックで、 `this.renderChart()`を呼び出します。 これでチャートインスタンスが作成されます。
49 |
50 | ```js{1,4,6}
51 | import { Bar } from 'vue-chartjs'
52 |
53 | export default {
54 | extends: Bar,
55 | mounted () {
56 | this.renderChart(data, options)
57 | }
58 | }
59 | ```
60 |
61 | :::tip
62 | `extends: Bar` または `mixins: [Bar]` どちらの記述方法でも使用できます。
63 | :::
64 |
65 | メソッドthis.renderChart()は、Barコンポーネントによって提供され、2つのパラメータを受け付けています。 どちらも`Object`です。 最初のものは表示するデータで、二番目のものはオプションを格納するオブジェクトです。
66 |
67 | チャート毎に必要なオブジェクト構造は公式 [Chart.js docs](http://www.chartjs.org/docs/latest/#creating-a-chart)をチェックしてください。
68 |
69 | ### Vue シングルファイルコンポーネント
70 |
71 | 本ドキュメントのほとんどの例はjavascriptファイルを基に記述されていて、 `.vue`ファイルの例はありません。 これはあなたが、たいてい必要なのは `
87 |
88 |
90 | ```
91 |
92 | ::: danger Template タグはマージできません
93 | `.vue`ファイルに`
`タグを含めないでください。 Vueはテンプレートを**マージすることはできません**。`.vue`ファイルに空の ``タグを追加すると、Vueは拡張されたものからではなく`.vue`のコンポーネントからテンプレートを取得します。その結果、空のテンプレートとエラーが発生します。
94 | :::
95 |
96 | ## チャートデータの更新
97 |
98 | Chart.js 自身ではデータセットを変更した場合に、ライブアップデートの機能を提供していません。 しかし`vue-chartjs`はこれを実現するために2つの mixin を提供します。
99 |
100 | - `reactiveProp`
101 | - `reactiveData`
102 |
103 | 両方のミックスインは実際には同じ結果を達成します。 ほとんどの場合は、`reactiveProp`を使います。 このミックスインはチャートコンポーネントのロジックを拡張し、自動的に `chartData`という名前のプロパティを作成し、このプロパティに`vue watch`を追加します。 データが変更されると、データセット内のデータだけが変更されていれば `update()`を、新しいデータセットが追加されていれば `renderChart()`を呼び出します。
104 |
105 | `ractiveData`はプロパティではないローカルのchartData変数を作成し、Watcherを追加します。 これは単一目的のチャートが必要でチャートコンポーネント内でAPI呼び出しを行う場合にのみ役に立ちます。
106 |
107 | ### 例
108 |
109 | **LineChart.js**
110 | ```javascript
111 | import { Line, mixins } from 'vue-chartjs'
112 | const { reactiveProp } = mixins
113 |
114 | export default {
115 | extends: Line,
116 | mixins: [reactiveProp],
117 | props: ['options'],
118 | mounted () {
119 | // this.chartData is created in the mixin.
120 | // If you want to pass options please create a local options object
121 | this.renderChart(this.chartData, this.options)
122 | }
123 | }
124 | ```
125 |
126 | **RandomChart.vue**
127 |
128 | ```javascript
129 |
130 |
131 |
132 | Randomize
133 |
134 |
135 |
136 |
174 |
175 |
181 | ```
182 |
183 | ::: danger 制限事項
184 | [注意事項](https://jp.vuejs.org/v2/guide/list.html#注意事項)
185 | [変更検出の注意事項](https://jp.vuejs.org/v2/guide/reactivity.html#変更検出の注意事項)
186 | [vm.$watch](https://jp.vuejs.org/v2/api/#vm-watch)
187 | :::
188 |
189 | ### イベント
190 | データが変更されると、リアクティブミックスインはイベントを発行します。 チャートコンポーネントの `v:on`でそれらを受け取ることができます。 以下のイベントがあります。
191 |
192 | - `chart:render` - ミックスインが完全にレンダリングしたとき
193 | - `chart:destroy` - ミックスインがチャートオブジェクトインスタンスを削除したとき
194 | - `chart:update` - ミックスインが再レンダリングの代わりに更新をしたとき
195 | - `labels:update` - labelsがセットされたとき
196 | - `xlabels:update` - xLabelsがセットされたとき
197 | - `ylabels:update` - yLabelsがセットされたとき
198 |
199 |
200 | ### トラブルシューティング
201 |
202 | 現状でのリアクティブシステムは**頑強**ではありません。 データを渡すためのユースケースや方法が多数あるため、それにはいくつかの問題が発生することがあります。
203 |
204 | #### オプション
205 |
206 | `options`オブジェクトは今のところリアクティブではありません。 そのため、チャートのオプションを動的に変更しても、それらはミックスインによって認識されません。
207 |
208 | ミックスインを使用している場合は、`options`というプロパティとしてオプションを渡す必要があります。 mixinがchart.jsの`update()`メソッドを呼び出すか、新しいチャートを破棄して描画する際に、これは重要です。 ミックスインが新しいチャートを描画するとき、`this.renderChart(this.chartData、this.options)`を呼び出します。
209 |
210 | しかし、オプションを `mounted()`フックで直接渡すと、それらは失われます。
211 |
212 | ::: danger 間違った方法
213 | ```js {7}
214 | import { Line, mixins } from 'vue-chartjs'
215 |
216 | export default {
217 | components: { Line }
218 | mixins: [mixins.reactiveProp],
219 | mounted () {
220 | this.renderChart(this.chartData, {responsive: true})
221 | }
222 | }
223 | ```
224 | :::
225 |
226 | ::: tip 正しい方法
227 | ```js {7}
228 | import { Line, mixins } from 'vue-chartjs'
229 |
230 | export default {
231 | components: { Line }
232 | mixins: [mixins.reactiveProp],
233 | mounted () {
234 | this.renderChart(this.chartData, this.options)
235 | }
236 | }
237 | ```
238 |
239 | :::
240 |
241 | #### 独自のウォッチャー
242 |
243 | (新しいデータをプッシュするのではなく)データをたくさん変更するのであれば、独自のウォッチャーを実装するのが一番良いやり方です。
244 | 必要に応じて、自分で `this.$data._chart.update()`または `this.renderChart()`を呼び出すことができます。
245 |
246 | シンプルなwatcherの実装例:
247 |
248 | ```js
249 | watch: {
250 | chartData () {
251 | this.$data._chart.update()
252 | }
253 | }
254 | ```
255 |
256 | ## 例
257 |
258 | ### propsを使用したチャート
259 |
260 | 目標は再利用可能なチャートコンポーネントを作成することです。 この目的のためには、オプションとチャートデータをVue.jsの props として渡す必要があります。 このようにすることで、チャート自体はデータの取得については気にせず、表示のみに注力できます。
261 |
262 | まずコンポーネントを作成します。
263 |
264 | ```js
265 | import { Line } from 'vue-chartjs'
266 |
267 | export default {
268 | extends: Line,
269 | props: {
270 | chartdata: {
271 | type: Object,
272 | default: null
273 | },
274 | options: {
275 | type: Object,
276 | default: null
277 | }
278 | },
279 | mounted () {
280 | this.renderChart(this.chartdata, this.options)
281 | }
282 | }
283 | ```
284 | その後、作成したチャートコンポーネントを親コンポーネントに追加できます。
285 |
286 | ```js
287 |
288 | ```
289 |
290 | ### ローカルデータを使用したチャート
291 |
292 | 独自のチャートコンポーネントでチャートデータを直接扱うことができます。 コンポーネント内のチャートデータを `renderChart()`メソッドに渡すだけです。
293 |
294 | ```js
295 | import { Bar } from 'vue-chartjs'
296 |
297 | export default {
298 | extends: Bar,
299 | data: () => ({
300 | chartdata: {
301 | datacollection: {
302 | labels: ['January', 'February'],
303 | datasets: [
304 | {
305 | label: 'Data One',
306 | backgroundColor: '#f87979',
307 | data: [40, 20]
308 | }
309 | ]
310 | }
311 | },
312 | options: {
313 | responsive: true,
314 | maintainAspectRatio: false
315 | }
316 | }),
317 |
318 | mounted () {
319 | this.renderChart(this.datacollection, this.options)
320 | }
321 | }
322 | ```
323 |
324 | ### APIから取得したデータを用いたチャート
325 |
326 |
327 | 一般的にはデータを取得するためにAPIを使用するのがパターンでしょう。しかし留意すべきことがいくつかあります。
328 | 最も一般的な問題は、チャートコンポーネントを直接マウントし、非同期API呼び出しからデータを渡すことです。
329 | このアプローチでの問題点は、chart.jsがチャートをレンダリングしてチャートデータにアクセスしようとしますが、API呼び出しが非同期だということです。 この時、データが到着する前にあなたはチャートを表示しようとしてしまいます。
330 |
331 | これを防ぐには、単純な `v-if`が最善の解決策です。
332 |
333 | データプロパティとオプションプロパティを使用してチャートコンポーネントを作成すると、コンテナコンポーネントからデータとオプションを渡すことができます。
334 |
335 | **Chart.vue**
336 |
337 | ```js
338 | import { Line } from 'vue-chartjs'
339 |
340 | export default {
341 | extends: Line,
342 | props: {
343 | chartdata: {
344 | type: Object,
345 | default: null
346 | },
347 | options: {
348 | type: Object,
349 | default: null
350 | }
351 | },
352 | mounted () {
353 | this.renderChart(this.chartdata, this.options)
354 | }
355 | }
356 | ```
357 |
358 | それから、あなたのAPIコールまたはVuex接続を処理するコンテナコンポーネントを作成します。
359 |
360 | **ChartContainer.vue**
361 |
362 | ```html {4}
363 |
364 |
365 |
369 |
370 |
371 |
372 |
394 | ```
395 |
396 | ### 動的スタイルを使用したチャート
397 |
398 | あなたは `responsive:true`をセットして外側のdivにインラインスタイルとして適用されるstylesオブジェクトを渡すことができます。 これにより、外側のコンテナの高さと幅を動的に変更できます。 これはchart.jsのデフォルトの動作ではありません。 これには計算プロパティを使用するのが最善です。
399 |
400 | ::: warning
401 | `position: relative`をセットする必要があります。
402 | :::
403 |
404 | ```html
405 |
406 |
407 |
408 | Increase height
409 |
410 |
411 |
412 |
434 | ```
435 |
436 | ### Custom / New Charts
437 |
438 | 場合によっては、デフォルトのChart.jsに用意されているチャートを拡張する必要があります。
439 | デフォルトチャートを拡張および変更する方法、あるいは独自のチャートタイプを作成する方法は、たくさんの[例](http://www.chartjs.org/docs/latest/developers/charts.html)があります。
440 |
441 | `vue-chartjs`でも、これとほぼ同じ方法で行うことができます。
442 |
443 | ```js
444 | // 1. Import Chart.js so you can use the global Chart object
445 | import Chart from 'chart.js'
446 | // 2. Import the `generateChart()` method to create the vue component.
447 | import { generateChart } from 'vue-chartjs'
448 |
449 | // 3. Extend on of the default charts
450 | // http://www.chartjs.org/docs/latest/developers/charts.html
451 | Chart.defaults.LineWithLine = Chart.defaults.line;
452 | Chart.controllers.LineWithLine = Chart.controllers.line.extend({ /* custom magic here */})
453 |
454 | // 4. Generate the vue-chartjs component
455 | // First argument is the chart-id, second the chart type.
456 | const CustomLine = generateChart('custom-line', 'LineWithLine')
457 |
458 | // 5. Extend the CustomLine Component just like you do with the default vue-chartjs charts.
459 |
460 | export default {
461 | extends: CustomLine,
462 | mounted () {
463 | // ....
464 | }
465 | }
466 | ```
467 |
468 | ## リソース
469 |
470 | `vue-chartjs`の使い方に関するチュートリアルのようないくつかのリソースがあります。
471 |
472 | - [Using vue-chartjs with WordPress](https://medium.com/@apertureless/wordpress-vue-and-chart-js-6b61493e289f)
473 | - [Create stunning Charts with Vue and Chart.js](https://hackernoon.com/creating-stunning-charts-with-vue-js-and-chart-js-28af584adc0a)
474 | - [Let’s Build a Web App with Vue, Chart.js and an API Part I](https://hackernoon.com/lets-build-a-web-app-with-vue-chart-js-and-an-api-544eb81c4b44)
475 | - [Let’s Build a Web App with Vue, Chart.js and an API Part II](https://hackernoon.com/lets-build-a-web-app-with-vue-chart-js-and-an-api-part-ii-39781b1d5acf)
476 | - [Build a realtime chart with VueJS and Pusher](https://blog.pusher.com/build-realtime-chart-with-vuejs-pusher/)
477 |
--------------------------------------------------------------------------------
/website/src/ja/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | home: true
3 | heroImage: https://raw.githubusercontent.com/apertureless/vue-chartjs/main/website/src/images/vue-chartjs.png
4 | actionText: 初めに →
5 | actionLink: /ja/guide/
6 | features:
7 | - title: 簡単
8 | details: 初心者にもプロにも簡単に始められる 🙌
9 | - title: 拡張性
10 | details: シンプルに使えて、拡張も簡単 💪
11 | - title: 強力
12 | details: chart.jsのフルパワーを持っている 💯
13 | footer: MIT Licensed | Copyright © 2018-present Jakub Juszczak
14 | ---
15 |
--------------------------------------------------------------------------------
/website/src/kr/api/index.md:
--------------------------------------------------------------------------------
1 | # 코딩 레퍼런스
2 |
3 | ## Props
4 |
5 | `vue-chartjs`가 제공하는 컴포넌트들은 몇 가지 기본적인 속성들을 정의한다. `확장`하고 있기 때문에, 그들은 * 보이지 않는 *이지만, 그 값을 덮어 쓸 수 있습니다 :
6 |
7 | | Prop 이름 | 설명 |
8 | |---|---|
9 | | width | 차트 폭 |
10 | | height | 차트 높이 |
11 | | chart-id | canvas 요소의 id |
12 | | css-classes | 둘러싸는 div css 클래스 (문자열) |
13 | | styles | 둘러싸는 div 의 css 클래스 (객체) |
14 | | plugins | chartjs 플러그인 (배열) |
15 |
16 | ## Events
17 |
18 | `reactData` 또는 `reactProp` 믹스 인이 사용되면 다음 이벤트가 발행됩니다.
19 |
20 | | 이벤트 이름 | 설명 |
21 | |---|---|
22 | | `chart:render` | 믹스 인이 완전히 렌더링 될 때 |
23 | | `chart:destroy` | 믹스인이 차트 오브젝트 인스턴스를 삭제할 때 |
24 | | `chart:update` | 믹스 인이 다시 렌더링 대신 업데이트를 할 때 |
25 | | `labels:update` | labels가 설정되면 |
26 | | `xlabels:update` | xlabels가 설정되면 |
27 | | `ylabels:update` | ylabels가 설정되면 |
28 |
29 | ## Global Methods
30 | 전역 메소드는 가져오고 사용합니다.
31 |
32 | ### generateChart
33 |
34 | - **Type:** `Function`
35 | - **Arguments**: `chart-id`, `chart-type`
36 | - **Usage:**
37 |
38 | ```js
39 | import { generateChart } from 'vue-chartjs'
40 | // First argument is the chart-id, second the chart type.
41 | const CustomLine = generateChart('custom-line', 'LineWithLine')
42 | ```
43 |
44 | ## Instance Methods
45 |
46 | 인스턴스 메소드는 독자적인 차트 컴퍼넌트내에서 사용할 수가 있습니다.
47 |
48 |
49 | ### generateLegend()
50 |
51 | HTML 범례를 만드는 도우미 함수
52 |
53 | - **Type:** `Function`
54 | - **Arguments**: `none`
55 | - **Usage:**
56 |
57 | ```js{11}
58 | import { Line } from 'vue-chartjs'
59 |
60 | export default {
61 | extends: Line,
62 | props: ['datasets', 'options']
63 | data: () => ({
64 | htmlLegend: null
65 | })
66 | mounted () {
67 | this.renderChart(this.datasets, this.options)
68 | this.htmlLegend = this.generateLegend()
69 | }
70 | }
71 |
72 | ```
73 |
74 | ### 플러그인 추가
75 |
76 | Chart.js에서는 글로벌 플러그인과 인라인 플러그인을 정의할 수 있습니다. 글로벌 플러그인은 [Chart.js docs] (http://www.chartjs.org/docs/latest/developers/plugins.html)에서 설명한대로 'vue-chartjs'에서도 잘 작동합니다. .
77 |
78 |
79 | 인라인 플러그인을 추가하려는 경우를 대비하여 `vue-chartjs`는 `addPlugin()`이라는 헬퍼 메소드를 노출합니다.
80 |
81 | `renderChart()` 메소드 앞에 `addPlugin()` 을 호출해야합니다.
82 |
83 | - **Type:** `Function`
84 | - **Arguments**: `Array` of Plugins
85 | - **Usage:**### 플러그인 추가
86 |
87 | ```js
88 | mounted () {
89 | this.addPlugin({
90 | id: 'my-plugin',
91 | beforeInit: function (chart) {
92 | ....
93 | }
94 | })
95 | }
96 | ```
97 |
98 | ### renderChart()
99 |
100 | Chart.js의 인스턴스를 만들고 그립니다.
101 |
102 | - **Type:** `Function`
103 | - **Arguments**: `Chart Data`, `Chart Options`
104 | - **Usage:**
105 |
106 | ```js
107 | mounted () {
108 | this.renderChart({
109 | labels: ['January', 'February'],
110 | datasets: [
111 | {
112 | label: 'Data One',
113 | backgroundColor: '#f87979',
114 | data: [40, 20]
115 | }
116 | ]},
117 | {
118 | responsive: true
119 | }
120 | )
121 | }
122 | ```
123 |
124 | ## Chart.js 객체
125 |
126 | 독자적인 차트 컴퍼넌트내로부터 Chart.js 의 오브젝트에는 `this.$data._chart` 로 액세스 할 수 있습니다.
127 |
128 | ## Canvas
129 |
130 | Canvas 요소는 `this.$refs.canvas`로 액세스 할 수 있습니다.
--------------------------------------------------------------------------------
/website/src/kr/guide/index.md:
--------------------------------------------------------------------------------
1 | # 시작하기
2 |
3 | **vue-chartjs**는 [Chart.js](https://github.com/chartjs/Chart.js)를 vue에서 사용하기 위한 래퍼입니다. 재사용 가능한 차트 구성 요소를 쉽게 만들 수 있습니다.
4 |
5 | ## 처음에
6 |
7 | `vue-chartjs` 너무 힘들지 않고 vue 안에서 chart.js를 사용할 수 있습니다. 간단한 차트를 가능한 한 빨리 시작하고 실행하고 싶은 사람에게 이상적입니다.
8 |
9 | chart.js의 기본 로직을 추상화하고 있지만 게시 된 chart.js의 객체를 사용하여 유연하게 사용자 정의 할 수 있습니다.
10 |
11 | ## 설치
12 |
13 | ### NPM
14 |
15 | `npm`을 사용하여 `vue-chartjs`를 설치할 수 있습니다. 그러나 프로젝트에 대한 종속성으로 `chart.js`를 추가해야합니다. 왜냐하면 `Chart.js`는 peerDependency이기 때문입니다. 따라서 Chart.js 버전을 완전히 제어할 수 있습니다.
16 |
17 | `yarn add vue-chartjs chart.js@2.9.4` or `npm install vue-chartjs chart.js@2.9.4 --save`
18 |
19 | ::: tip
20 | Vue.js의 버전 1.x를 사용하는 경우 `legacy` 태그를 사용하십시오. 그러나 vue의 버전 1은 더 이상 유지 보수되지 않습니다.
21 |
22 | `yarn add vue-chartjs@legacy`
23 | :::
24 |
25 | ### 브라우저
26 |
27 | 브라우저에서 직접 `vue-chartjs`를 사용할 수 있습니다.
28 | 먼저 `Chart.js` 스크립트를 추가하고`vue-chartjs` 스크립트를 추가하십시오.
29 |
30 | ``html
31 |
32 |
33 | ``
34 |
35 | ## 통합
36 |
37 | `Chart.js`에서 사용 가능한 모든 차트 유형은 명명된 컴포넌트로 내보내져 그대로 가져올 수 있습니다. 이러한 컴포넌트는 일반적인 Vue 컴포넌트이지만 그것을 `확장`해야합니다.
38 |
39 | `vue-chartjs` 뒤에 있는 아이디어는 최대한의 유연성과 확장성을 가지며 사용하기 쉬운 컴포넌트를 제공하는 것이다. 이것을 실현하려면 , 독자적인 *Chart Component* 를 작성해, 그것을 `vue-chartjs` 컴퍼넌트해 제공하도록 확장할 필요가 있습니다.
40 |
41 | 확장하면 차트 구성 요소의 메서드와 논리가 자체 차트 구성 요소에 병합됩니다.
42 |
43 | ## 첫 번째 차트 만들기
44 |
45 | BaseChart를 가져오고 확장합니다. 이 방법으로 다른 데이터의 차트를 볼 때 유연성이 크게 향상됩니다.
46 | 구성 요소를 캡슐화하고 속성을 사용하여 구성 요소의 데이터에 전달하거나 구성 요소에 직접 데이터를 설명할 수 있습니다. 다만 직접 컴퍼넌트내에 데이터를 기술했을 경우는 재이용을 할 수 없습니다.
47 |
48 | 전체 패키지 또는 각 모듈을 개별적으로 가져올 수 있습니다. 가져온 것을 `extends:` 또는 `mixins:[]`를 사용하여 지정합니다. 또한 `mounted()` 후크에서 `this.renderChart()`를 호출합니다. 이제 차트 인스턴스가 생성됩니다.
49 |
50 |
51 | ``js {1,4,6}
52 | import { Bar } from 'vue-chartjs'
53 |
54 | export default {
55 | extends: Bar,
56 | mounted () {
57 | this.renderChart(data, options)
58 | }
59 | }
60 | ``
61 |
62 | :::tip
63 | `extends: Bar` 또는 `mixins: [Bar]` 어느 쪽의 기술 방법으로도 사용할 수 있습니다.
64 | :::
65 |
66 | this.renderChart() 메서드는 Bar 구성 요소에서 제공하며 두 개의 매개 변수를 허용합니다. 둘 다 `Object`입니다. 첫 번째는 표시할 데이터이고 두 번째는 옵션을 저장하는 개체입니다.
67 |
68 | 각 차트에 필요한 객체 구조는 공식 [Chart.js docs] (http://www.chartjs.org/docs/latest/#creating-a-chart)을 확인하십시오.
69 |
70 | ### Vue 단일 파일 구성 요소
71 |
72 | 이 문서의 대부분의 예는 javascript 파일을 기반으로 작성되었으며 `.vue` 파일의 예는 없습니다. 이것은 당신이 '
88 |
89 |
91 | ``
92 |
93 | ::: danger Template 태그는 병합할 수 없습니다.
94 | `.vue` 파일에 `` 태그를 포함하지 마십시오. Vue는 템플릿을 **병합할 수 없습니다**. `.vue` 파일에 빈 `` 태그를 추가하면 Vue는 확장된 것이 아니라 `.vue` 컴포넌트에서 템플릿을 가져옵니다. 그 결과 빈 템플릿과 오류가 발생합니다.
95 | :::
96 |
97 | ## 차트 데이터 업데이트
98 |
99 | v4부터 차트는 기본적으로 데이터 변경 `watch`와 옵션 변경 `watch`가 있으므로 새 데이터 또는 새 옵션이 전달되면 (변경되면) Vue Chart 래퍼가 차트를 업데이트하거나 다시 렌더링합니다. v4부터는 믹스인이 제거되었습니다.
100 |
101 | ### 예제
102 |
103 | ```vue
104 |
105 |
106 |
107 |
108 |
124 | ```
125 |
126 | 차트 데이터를 업데이트할 때 Vue의 `Target is read only` 경고가 나타날 수 있습니다.
127 |
128 | 데이터가 '읽기 전용' (`read only`) 반응 값인 경우 클론을 사용하여 이 경고를 재정의할 수 있습니다
129 |
130 | ```vue
131 |
132 |
133 |
134 | ```
135 |
136 | 차트 데이터가 수정 가능한 계산된 속성 경우 [writable computed value](https://vuejs.org/guide/essentials/computed#writable-computed) 클론을 사용할 필요가 없습니다
137 |
138 | **RandomChart.vue**
139 |
140 | ```javascript
141 |
142 |
143 |
144 | Randomize
145 |
146 |
147 |
148 |
186 |
187 |
193 | ```
194 |
195 | ::: danger 제한 사항
196 | [주의 사항] (https://kr.vuejs.org/v2/guide/list.html#주의 사항)
197 | [변경 탐지주의 사항] (https://kr.vuejs.org/v2/guide/reactivity.html# 변경 탐지주의 사항)
198 | [vm.$watch](https://kr.vuejs.org/v2/api/#vm-watch)
199 | :::
200 |
201 | ### 이벤트
202 | 데이터가 변경되면 리액티브 믹스 인은 이벤트를 발행합니다. 차트 컴포넌트의 `v:on`에서 이를 받을 수 있습니다. 다음 이벤트가 있습니다.
203 |
204 |
205 | - `chart : render` - 믹스 인이 완전히 렌더링 될 때
206 | - `chart : destroy` - 믹스 인이 차트 객체 인스턴스를 삭제할 때
207 | - `chart : update` - 믹스 인이 다시 렌더링 대신 업데이트를 할 때
208 | - `labels : update` - labels가 설정되면
209 | - `xlabels : update` - xLabels가 설정되면
210 | - `ylabels : update` - yLabels가 설정되면
211 |
212 |
213 | ### 문제 해결
214 |
215 | 현재의 리액티브 시스템은 **강력**이 아닙니다. 데이터를 전달하는 유스 케이스와 방법이 많기 때문에 몇 가지 문제가 발생할 수 있습니다.
216 |
217 | #### 옵션
218 |
219 | `options` 객체는 현재 리액티브가 아니다. 따라서 차트 옵션을 동적으로 변경해도 믹스인이 인식하지 못합니다.
220 |
221 | 믹스 인을 사용하는 경우 옵션을 `options`라는 속성으로 전달해야합니다. mixin이 chart.js의 `update()` 메소드를 호출하거나 새로운 차트를 파기하고 그릴 때 이것은 중요합니다. 믹스 인이 새로운 차트를 그릴 때 `this.renderChart(this.chartData, this.options)`를 호출합니다.
222 |
223 | 그러나 옵션을 `mounted()` 훅으로 직접 전달하면 잃어버립니다.
224 |
225 | ::: danger 잘못된 방법
226 | ```js {7}
227 | import { Line, mixins } from 'vue-chartjs'
228 |
229 | export default {
230 | components: { Line }
231 | mixins: [mixins.reactiveProp],
232 | mounted () {
233 | this.renderChart(this.chartData, {responsive: true})
234 | }
235 | }
236 | ```
237 | :::
238 |
239 | ::: tip 正しい方法
240 | ```js {7}
241 | import { Line, mixins } from 'vue-chartjs'
242 |
243 | export default {
244 | components: { Line }
245 | mixins: [mixins.reactiveProp],
246 | mounted () {
247 | this.renderChart(this.chartData, this.options)
248 | }
249 | }
250 | ```
251 |
252 | :::
253 |
254 | #### 자신의 감시자
255 |
256 | (새로운 데이터를 푸시하는 대신) 데이터를 많이 변경한다면, 자신의 감시자를 구현하는 것이 가장 좋은 방법입니다.
257 | 필요에 따라서, 스스로 `this.$data._chart.update()` 또는 `this.renderChart()`를 호출할 수가 있습니다.
258 |
259 | 간단한 watcher 구현 예 :
260 |
261 | ```js
262 | watch: {
263 | chartData () {
264 | this.$data._chart.update()
265 | }
266 | }
267 | ```
268 |
269 | ## 예제
270 |
271 | ### props를 사용한 차트
272 |
273 | 목표는 재사용 가능한 차트 구성 요소를 만드는 것입니다. 이를 위해 옵션과 차트 데이터를 Vue.js의 props로 전달해야합니다. 이런 식으로 차트 자체는 데이터 검색에 대해 신경 쓰지 않고 표시에만 집중할 수 있습니다.
274 |
275 | 먼저 구성 요소를 만듭니다.
276 |
277 | ```js
278 | import { Line } from 'vue-chartjs'
279 |
280 | export default {
281 | extends: Line,
282 | props: {
283 | chartdata: {
284 | type: Object,
285 | default: null
286 | },
287 | options: {
288 | type: Object,
289 | default: null
290 | }
291 | },
292 | mounted () {
293 | this.renderChart(this.chartdata, this.options)
294 | }
295 | }
296 | ```
297 | 그런 다음 작성한 차트 구성 요소를 상위 구성 요소에 추가할 수 있습니다.
298 |
299 | ```js
300 |
301 | ```
302 |
303 | ### 로컬 데이터를 사용한 차트
304 |
305 | 고유한 차트 구성 요소로 차트 데이터를 직접 처리할 수 있습니다. 컴퍼넌트내의 차트 데이터를 `renderChart()` 메소드에 건네줄 뿐입니다.
306 |
307 | ```js
308 | import { Bar } from 'vue-chartjs'
309 |
310 | export default {
311 | extends: Bar,
312 | data: () => ({
313 | chartdata: {
314 | datacollection: {
315 | labels: ['January', 'February'],
316 | datasets: [
317 | {
318 | label: 'Data One',
319 | backgroundColor: '#f87979',
320 | data: [40, 20]
321 | }
322 | ]
323 | }
324 | },
325 | options: {
326 | responsive: true,
327 | maintainAspectRatio: false
328 | }
329 | }),
330 |
331 | mounted () {
332 | this.renderChart(this.datacollection, this.options)
333 | }
334 | }
335 | ```
336 |
337 | ### API에서 얻은 데이터를 사용한 차트
338 |
339 |
340 | 일반적으로 데이터를 검색하기 위해 API를 사용하는 것이 패턴입니다. 그러나 유의해야 할 몇 가지가 있습니다.
341 | 가장 일반적인 문제는 차트 구성 요소를 직접 마운트하고 비동기 API 호출에서 데이터를 전달하는 것입니다.
342 | 이 접근 방식의 문제점은 chart.js가 차트를 렌더링하고 차트 데이터에 액세스하려고 시도하지만 API 호출이 비동기라는 것입니다. 이 때 데이터가 도착하기 전에 차트를 표시하려고합니다.
343 |
344 | 이것을 막기 위해서는 간단한 `v-if`가 가장 좋은 해결책입니다.
345 |
346 | 데이터 속성과 옵션 속성을 사용하여 차트 구성 요소를 만들면 컨테이너 구성 요소에서 데이터와 옵션을 전달할 수 있습니다.
347 |
348 | **Chart.vue**
349 |
350 | ```js
351 | import { Line } from 'vue-chartjs'
352 |
353 | export default {
354 | extends: Line,
355 | props: {
356 | chartdata: {
357 | type: Object,
358 | default: null
359 | },
360 | options: {
361 | type: Object,
362 | default: null
363 | }
364 | },
365 | mounted () {
366 | this.renderChart(this.chartdata, this.options)
367 | }
368 | }
369 | ```
370 |
371 | 그런 다음 API 호출 또는 Vuex 연결을 처리하는 컨테이너 구성 요소를 만듭니다.
372 |
373 | **ChartContainer.vue**
374 |
375 | ```html {4}
376 |
377 |
378 |
382 |
383 |
384 |
385 |
407 | ```
408 |
409 | ### 동적 스타일을 사용한 차트
410 |
411 | 당신은 `responsive:true`를 설정하고 외부 div에 인라인 스타일로 적용되는 styles 객체를 전달할 수 있습니다. 이렇게 하면 외부 컨테이너의 높이와 너비를 동적으로 변경할 수 있습니다. 이것은 chart.js의 기본 동작이 아닙니다. 이것은 계산 속성을 사용하는 것이 가장 좋습니다.
412 |
413 | ::: warning
414 | `position: relative`를 설정해야합니다.
415 | :::
416 |
417 | ```html
418 |
419 |
420 |
421 | Increase height
422 |
423 |
424 |
425 |
447 | ```
448 |
449 | ### Custom/New Charts
450 |
451 | 경우에 따라 기본 Chart.js에 제공된 차트를 확장해야 합니다.
452 | 기본 차트를 확장하고 수정하는 방법 또는 자체 차트 유형을 만드는 방법에는 많은 예(http://www.chartjs.org/docs/latest/developers/charts.html)가 있습니다.
453 |
454 | `vue-chartjs`도 이것과 거의 같은 방법으로 할 수 있습니다.### Custom/New Charts
455 |
456 | 경우에 따라 기본 Chart.js에 제공된 차트를 확장해야 합니다.
457 | 기본 차트를 확장하고 수정하는 방법 또는 자체 차트 유형을 만드는 방법에는 많은 예(http://www.chartjs.org/docs/latest/developers/charts.html)가 있습니다.
458 |
459 | `vue-chartjs`도 이것과 거의 같은 방법으로 할 수 있습니다.
460 |
461 | ```js
462 | // 1. Import Chart.js so you can use the global Chart object
463 | import Chart from 'chart.js'
464 | // 2. Import the `generateChart()` method to create the vue component.
465 | import { generateChart } from 'vue-chartjs'
466 |
467 | // 3. Extend on of the default charts
468 | // http://www.chartjs.org/docs/latest/developers/charts.html
469 | Chart.defaults.LineWithLine = Chart.defaults.line;
470 | Chart.controllers.LineWithLine = Chart.controllers.line.extend({ /* custom magic here */})
471 |
472 | // 4. Generate the vue-chartjs component
473 | // First argument is the chart-id, second the chart type.
474 | const CustomLine = generateChart('custom-line', 'LineWithLine')
475 |
476 | // 5. Extend the CustomLine Component just like you do with the default vue-chartjs charts.
477 |
478 | export default {
479 | extends: CustomLine,
480 | mounted () {
481 | // ....
482 | }
483 | }
484 | ```
485 |
486 | ## 리소스
487 |
488 | `vue-chartjs`를 사용하는 방법에 대한 자습서와 같은 몇 가지 리소스가 있습니다.
489 |
490 | - [Using vue-chartjs with WordPress](https://medium.com/@apertureless/wordpress-vue-and-chart-js-6b61493e289f)
491 | - [Create stunning Charts with Vue and Chart.js](https://hackernoon.com/creating-stunning-charts-with-vue-js-and-chart-js-28af584adc0a)
492 | - [Let’s Build a Web App with Vue, Chart.js and an API Part I](https://hackernoon.com/lets-build-a-web-app-with-vue-chart-js-and-an-api-544eb81c4b44)
493 | - [Let’s Build a Web App with Vue, Chart.js and an API Part II](https://hackernoon.com/lets-build-a-web-app-with-vue-chart-js-and-an-api-part-ii-39781b1d5acf)
494 | - [Build a realtime chart with VueJS and Pusher](https://blog.pusher.com/build-realtime-chart-with-vuejs-pusher/)- [Using vue-chartjs with WordPress](https://medium.com/@apertureless/wordpress-vue-and-chart-js-6b61493e289f)
495 | - [Create stunning Charts with Vue and Chart.js](https://hackernoon.com/creating-stunning-charts-with-vue-js-and-chart-js-28af584adc0a)
496 | - [Let’s Build a Web App with Vue, Chart.js and an API Part I](https://hackernoon.com/lets-build-a-web-app-with-vue-chart-js-and-an-api-544eb81c4b44)
497 | - [Let’s Build a Web App with Vue, Chart.js and an API Part II](https://hackernoon.com/lets-build-a-web-app-with-vue-chart-js-and-an-api-part-ii-39781b1d5acf)
498 | - [Build a realtime chart with VueJS and Pusher](https://blog.pusher.com/build-realtime-chart-with-vuejs-pusher/)
--------------------------------------------------------------------------------
/website/src/kr/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | home: true
3 | heroImage: https://raw.githubusercontent.com/apertureless/vue-chartjs/main/website/src/images/vue-chartjs.png
4 | actionText: 시작하기 →
5 | actionLink: /ja/guide/
6 | features:
7 | - title: 간편성
8 | details: 숙련자 뿐만 아니라 숙련자도 쉽게 시작할 수 있습니다 🙌
9 | - title: 확장성
10 | details: 심플하게 사용할 수 있고 확장도 간단 합니다 💪
11 | - title: 강력한 기능
12 | details: chart.js의 모든 기능을 가지고 있습니다. 💯
13 | footer: MIT Licensed | Copyright © 2018-present Jakub Juszczak
14 | ---
--------------------------------------------------------------------------------
/website/src/migration-guides/index.md:
--------------------------------------------------------------------------------
1 | ## Migration from v4 to v5
2 |
3 | With v5, this library introduces a number of breaking changes
4 |
5 | ### ESM
6 |
7 | #### v5.0
8 |
9 | Chart.js v4 and vue-chartjs v5 are [ESM-only packages](https://nodejs.org/api/esm.html). To use them in your project, it also should be ESM:
10 |
11 | ```json
12 | // package.json
13 | {
14 | "type": "module"
15 | }
16 | ```
17 |
18 | If you are experiencing this problem with Jest, you should follow [this doc](https://jestjs.io/docs/ecmascript-modules) to enable ESM support. Or, we can recommend you migrate to [Vitest](https://vitest.dev/). Vitest has ESM support out of the box and [has almost the same API as Jest](https://vitest.dev/guide/migration.html#migrating-from-jest). [Here is our example of migration](https://github.com/reactchartjs/react-chartjs-2/commit/7f3ec96101d21e43cae8cbfe5e09a46a17cff1ef).
19 |
20 |
21 | #### v5.1
22 |
23 | Chart.js v4.1 and vue-chartjs v5.1 have restored the CommonJS support.
24 |
25 | ### API changes
26 |
27 | - `chartData` props were renamed to `data`
28 | - `chartOptions` props were renamed to `options`
29 | - unknown props will fall through to the canvas element.
30 | - `generateChart` were refactored and renamed to `createTypedChart`
31 | - Vue.js < 2.7 is no longer supported. If you want to use vue-chartjs with Vue < 2.7 you have to lock your version to 4.x.
32 |
33 | ## Migration from v3 to v4
34 |
35 | With v4, this library introduces a number of breaking changes. In order to improve performance, offer new features, and improve maintainability, it was necessary to break backwards compatibility, but we aimed to do so only when worth the benefit.
36 |
37 | v4 is fully compatible with Chart.js v3.
38 |
39 | ### Tree-shaking
40 |
41 | v4 of this library, [just like Chart.js v3](https://www.chartjs.org/docs/latest/getting-started/v3-migration.html#setup-and-installation), is tree-shakable. It means that you need to import and register the controllers, elements, scales, and plugins you want to use.
42 |
43 | For a list of all the available items to import, see [Chart.js docs](https://www.chartjs.org/docs/latest/getting-started/integration.html#bundlers-webpack-rollup-etc).
44 |
45 | v3:
46 |
47 | ```javascript
48 | import { Bar } from 'vue-chartjs'
49 | ```
50 |
51 | v4 — lazy way:
52 |
53 | ```javascript
54 | import 'chart.js/auto';
55 | import { Bar } from 'vue-chartjs'
56 | ```
57 |
58 | v4 — tree-shakable way:
59 |
60 | ```javascript
61 | import { Bar } from 'vue-chartjs'
62 | import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale } from 'chart.js'
63 |
64 | ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)
65 | ```
66 |
67 | Using the "lazy way" is okay to simplify the migration, but please consider using the tree-shakable way to decrease the bundle size.
68 |
69 | Please note that typed chart components register their controllers by default, so you don't need to register them by yourself. For example, when using the Pie component, you don't need to register PieController explicitly.
70 |
71 | ```javascript
72 | import { Pie } from 'vue-chartjs'
73 | import { Chart as ChartJS, Title, Tooltip, Legend, ArcElement, CategoryScale } from 'chart.js'
74 |
75 | ChartJS.register(Title, Tooltip, Legend, ArcElement, CategoryScale)
76 | ```
77 |
78 | ### Changing the creation of Charts
79 |
80 | In v3, you needed to import the component, and then either use extends or mixins and add it.
81 |
82 | v3:
83 |
84 | ```javascript
85 | // BarChart.js
86 | import { Bar } from 'vue-chartjs'
87 |
88 | export default {
89 | extends: Bar,
90 | mounted () {
91 | // Overwriting base render method with actual data.
92 | this.renderChart({
93 | labels: ['January', 'February', 'March'],
94 | datasets: [
95 | {
96 | label: 'GitHub Commits',
97 | backgroundColor: '#f87979',
98 | data: [40, 20, 12]
99 | }
100 | ]
101 | })
102 | }
103 | }
104 | ```
105 |
106 | ```vue
107 |
108 |
109 |
110 |
111 |
119 | ```
120 |
121 | In v4, you need to import the component, pass props to it, and use Chart component as a standard Vue component.
122 |
123 | ```vue
124 |
125 |
126 |
127 |
128 |
154 | ```
155 |
156 | ### New reactivity system
157 |
158 | v3 does not update or re-render the chart if new data is passed. You needed to use `reactiveProp` and `reactiveData` mixins for that.
159 |
160 | v3:
161 |
162 | ```javascript
163 | import { Line, mixins } from 'vue-chartjs'
164 |
165 | export default {
166 | extends: Line,
167 | mixins: [mixins.reactiveProp],
168 | props: ['chartData', 'options'],
169 | mounted () {
170 | this.renderChart(this.chartData, this.options)
171 | }
172 | }
173 | ```
174 |
175 | v4 charts have data change watcher by default. v4 will update or re-render the chart if new data is passed. Mixins have been removed.
176 |
177 | v4:
178 |
179 | ```vue
180 |
181 |
182 |
183 |
184 |
199 | ```
200 |
201 | ## Migration from vue-chart-3
202 |
203 | ### Uninstall vue-chart-3
204 |
205 | ```bash
206 | pnpm rm vue-chart-3
207 | # or
208 | yarn remove vue-chart-3
209 | # or
210 | npm uninstall vue-chart-3
211 | ```
212 |
213 | ### Install vue-chartjs
214 |
215 | ```bash
216 | pnpm add vue-chartjs
217 | # or
218 | yarn add vue-chartjs
219 | # or
220 | npm i vue-chartjs
221 | ```
222 |
223 | ### Change component import path
224 |
225 | For Vue 2.7 and Vue 3 projects:
226 |
227 | ```javascript
228 | import { /* component */ } from 'vue-chartjs'
229 | ```
230 |
231 | For Vue 2 (<2.7) projects:
232 |
233 | ```javascript
234 | import { /* component */ } from 'vue-chartjs/legacy'
235 | ```
236 |
237 | ### Rename components
238 |
239 | - BarChart to Bar
240 | - DoughnutChart to Doughnut
241 | - LineChart to Line
242 | - PieChart to Pie
243 | - PolarAreaChart to PolarArea
244 | - RadarChart to Radar
245 | - BubbleChart to Bubble
246 | - ScatterChart to Scatter
247 |
248 | ### Rename props
249 |
250 | - options to chartOptions
251 |
--------------------------------------------------------------------------------
/website/src/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-chartjs-docs",
3 | "private": true
4 | }
5 |
--------------------------------------------------------------------------------
/website/src/pt-br/api/index.md:
--------------------------------------------------------------------------------
1 | # Referência de codificação
2 |
3 | ## Props
4 |
5 | Existem alguns props básicas definidas nos componentes fornecidos pelo `vue-chartjs`. Porque você os `estende`, eles são _invisíveis_, mas você pode substituí-los:
6 |
7 | | Prop | Descrição |
8 | | ----------- | ------------------------------------------------------- |
9 | | width | largura do gráfico |
10 | | height | altura do gráfico |
11 | | chart-id | Id da tela |
12 | | css-classes | String com classes css para a div circundante |
13 | | styles | Objeto com estilos css para o div contêiner circundante |
14 | | plugins | Array com plugins chartjs |
15 |
16 | ## Eventos
17 |
18 | Se o mixin `reactiveData` ou `reactiveProp` estiver anexado, os seguintes eventos serão emitidos:
19 |
20 | | Evento | Descrição |
21 | | ---------------- | ------------------------------------------------------------------- |
22 | | `chart:render` | se o mixin executar um renderizador completo |
23 | | `chart:destroy` | se o mixin excluir a instância do objeto de gráfico |
24 | | `chart:update` | se o mixin executar uma atualização em vez de uma nova renderização |
25 | | `labels:update` | se novos labals foram definidos |
26 | | `xlabels:update` | se novos xLabels foram definidos |
27 | | `ylabels:update` | se novos yLabels foram definidos |
28 |
29 | ## Métodos Globais
30 |
31 | Os métodos globais precisam ser importados.
32 |
33 | ### generateChart
34 |
35 | - **Tipo:** `Function`
36 | - **Argumentos**: `chart-id`, `chart-type`
37 | - **Uso:**
38 |
39 | ```js
40 | import { generateChart } from "vue-chartjs";
41 | // O primeiro argumento é o ID do gráfico, depois o tipo de gráfico.
42 | const CustomLine = generateChart("custom-line", "LineWithLine");
43 | ```
44 |
45 | ## Métodos de instância
46 |
47 | Os métodos de instância podem ser usados dentro do componente do gráfico.
48 |
49 | ### generateLegend()
50 |
51 | Função auxiliar para gerar uma legenda HTML.
52 |
53 | - **Tipo:** `Function`
54 | - **Argumentos**: `none`
55 | - **Uso:**
56 |
57 | ```js{11}
58 | import { Line } from 'vue-chartjs'
59 |
60 | export default {
61 | extends: Line,
62 | props: ['datasets', 'options']
63 | data: () => ({
64 | htmlLegend: null
65 | })
66 | mounted () {
67 | this.renderChart(this.datasets, this.options)
68 | this.htmlLegend = this.generateLegend()
69 | }
70 | }
71 |
72 | ```
73 |
74 | ### addPlugin
75 |
76 | No Chart.js, você pode definir plugins globais e embutidos. Os plug-ins globais estão funcionando sem problemas com o `vue-chartjs` como descrito no [Chart.js docs](http://www.chartjs.org/docs/latest/developers/plugins.html).
77 |
78 | Se você deseja adicionar plug-ins embutidos, `vue-chartjs` expõe um método auxiliar chamado `addPlugin()`
79 | Você deve chamar `addPlugin()` antes do método `renderChart()`.
80 |
81 | - **Tipo:** `Function`
82 | - **Argumentos**: `Array` de Plugins
83 | - **Uso:**
84 |
85 | ```js
86 | mounted () {
87 | this.addPlugin({
88 | id: 'my-plugin',
89 | beforeInit: function (chart) {
90 | ...
91 | }
92 | })
93 | }
94 | ```
95 |
96 | ### renderChart()
97 |
98 | Cria uma instância Chart.js e renderiza o gráfico.
99 |
100 | - **Tipo:** `Function`
101 | - **Argumentos**: `Chart Data`, `Chart Options`
102 | - **Uso:**
103 |
104 | ```js
105 | mounted () {
106 | this.renderChart({
107 | labels: ['January', 'February'],
108 | datasets: [
109 | {
110 | label: 'Data One',
111 | backgroundColor: '#f87979',
112 | data: [40, 20]
113 | }
114 | ]},
115 | {
116 | responsive: true
117 | }
118 | )
119 | }
120 | ```
121 |
122 | ## Objeto Chart.js
123 |
124 | Você pode acessar o objeto Chart.js dentro do componente do gráfico com `this.$data._chart`
125 |
126 | ## Canvas
127 |
128 | Você pode acessar canvas com `this.$refs.canvas`
129 |
--------------------------------------------------------------------------------
/website/src/pt-br/guide/index.md:
--------------------------------------------------------------------------------
1 | # Começando
2 |
3 | **vue-chartjs** é um pacote para [Chart.js](https://github.com/chartjs/Chart.js) no Vue. Com ele você pode criar facilmente componentes de gráficos reutilizáveis.
4 |
5 | ## Introdução
6 |
7 | `vue-chartjs` permite você usar Chart.js sem muito aborrecimento dentro do Vue. É perfeito para pessoas que precisam de gráficos simples em funcionamento o mais rápido possível.
8 |
9 | Abstrai a lógica básica, mas expõe o objeto Chart.js para oferecer a máxima flexibilidade.
10 |
11 | ## Instalação
12 |
13 | ### NPM
14 |
15 | Você pode instalar o `vue-chartjs` através do `npm` ou `yarn`. No entanto, você também precisa adicionar o `chart.js` como uma dependência ao seu projeto, porque o `Chart.js` é um parDeDependência. Dessa forma, você tem total controle sobre o versionamento do `Chart.js`.
16 |
17 | ```bash
18 | npm install vue-chartjs chart.js --save
19 | ```
20 |
21 | ```bash
22 | yarn add vue-chartjs chart.js
23 | ```
24 |
25 | ::: tip Dica
26 | Se você estiver utilizando vue 1.x por favor use a tag `legacy`. No entanto, a versão 1 do Vue não é mais mantida.
27 |
28 | `yarn add vue-chartjs@legacy`
29 | :::
30 |
31 | ### Navegador
32 |
33 | Você também pode usar `vue-chartjs` diretamente no navegador via CDN.
34 | Primeiro, adicione o script do `Chart.js`, e depois adicione o script `vue-chartjs`.
35 |
36 | ```html
37 |
38 |
39 | ```
40 |
41 | ## Integração
42 |
43 | Todo tipo de gráfico disponível em `Chart.js` é exportado como um componente nomeado e pode ser importado como tal. Esses componentes são componentes normais do Vue, no entanto, você precisa estendê-lo com `extend`.
44 |
45 | A ideia por trás do `vue-chartjs` é fornecer componentes fáceis de usar, com máxima flexibilidade e extensibilidade. Para alcançar isto, você precisa criar o seu próprio _Componente de gráfico_ e estendê-lo com os componentes `vue-chartjs` fornecidos.
46 |
47 | Dessa forma, os métodos e a lógica nos componentes do gráfico são mesclados no seu próprio componente de gráfico.
48 |
49 | ## Criando seu primeiro Gráfico
50 |
51 | primeiro, você precisa importar o gráfico base e estendê-lo. Isso oferece mais flexibilidade ao trabalhar com dados diferentes. Você pode encapsular seus componentes e usar objetos para passar dados, ou você pode inseri-los diretamente dentro do componente. No entanto, seu componente não é reutilizável dessa maneira.
52 |
53 | Você pode importar o pacote inteiro ou cada módulo individualmente. Então, você precisa usar `extends:` ou `mixins:[]`. Depois, no gancho `mounted()`, chame `this.renderChart()`. Isso criará sua instância do gráfico.
54 |
55 | ```js{1,4,6}
56 | import { Bar } from "vue-chartjs";
57 |
58 | export default {
59 | extends: Bar,
60 | mounted() {
61 | this.renderChart(data, options);
62 | }
63 | };
64 | ```
65 |
66 | :::tip Dica
67 | Você pode usar `extends: Bar` ou `mixins: [Bar]`
68 | :::
69 |
70 | O método `this.renderChart()` é fornecido pelo componente `Bar` e aceita dois parâmetros: ambos são `objetos`. O primeiro são os dados do gráfico, e o segundo é um objeto de opções.
71 |
72 | Confira o oficial [Chart.js docs](http://www.chartjs.org/docs/latest/#creating-a-chart) para ver a estrutura do objeto que você precisa fornecer.
73 |
74 | ### Componentes de arquivo único do Vue
75 |
76 | A maioria dos exemplos nos documentos é baseada em arquivos JavaScript e não em arquivos `.vue`. Isso ocorre porque, principalmente, você precisará apenas do bloco `
92 |
93 |
95 | ```
96 |
97 | ::: danger A tag template não pode ser mesclada
98 | Não inclua a tag `` em seus componentes single-file `.vue`. Vue pode **não** mesclar templates. Se você adicionar uma tag `` vazia, o Vue pegará o modelo do seu componente e não do estendido, o que resultará em um template vazio e erros inesperados.
99 | :::
100 |
101 | ## Atualizando Gráficos
102 |
103 | `Chart.js` não fornece uma atualização ao vivo se você alterar os conjuntos de dados. No entanto, `vue-chartjs` fornece dois mixins para atingir esse objetivo:
104 |
105 | - `reactiveProp`
106 | - `reactiveData`
107 |
108 | Ambos os mixins alcançam o mesmo resultado. Na maioria das vezes você usará `reactiveProp`. Ele estende a lógica do seu componente de gráfico e cria automaticamente um objeto chamado `chartData` e adiciona um `vue watch` neste objeto. Na mutação de dados, ele chamará `update()` se os dados dentro dos conjuntos de dados foram alterados, ou `renderChart()` se novos conjuntos de dados foram adicionados.
109 |
110 | `reactiveData` simplesmente cria uma variável local `chartData` (o que não é um `objeto`!) e adiciona um observador. Isso é útil apenas se você precisar de gráficos de finalidade única ou precisar de uma chamada de API dentro do componente do gráfico.
111 |
112 | ### Exemplo
113 |
114 | **LineChart.js**
115 |
116 | ```js
117 | import { Line, mixins } from "vue-chartjs";
118 | const { reactiveProp } = mixins;
119 |
120 | export default {
121 | extends: Line,
122 | mixins: [reactiveProp],
123 | props: ["options"],
124 | mounted() {
125 | // this.chartData é criado no mixin.
126 | // Se você deseja passar opções, crie um objeto de opções locais
127 | this.renderChart(this.chartData, this.options);
128 | }
129 | };
130 | ```
131 |
132 | **RandomChart.vue**
133 |
134 | ```vue
135 |
136 |
137 |
138 | Randomize
139 |
140 |
141 |
142 |
181 |
182 |
188 | ```
189 |
190 | ::: danger Limitações
191 |
192 | [Caveats](https://vuejs.org/v2/guide/list.html#Caveats)
193 | [Change-Detection-Caveats](https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats)
194 | [vm.\$watch](https://vuejs.org/v2/api/#vm-watch)
195 |
196 | :::
197 |
198 | ### Eventos
199 |
200 | Esses mixins reativos emitem eventos se os dados forem alterados. Você pode ouvi-los com `v:on` no componente do gráfico. Os seguintes eventos estão disponíveis:
201 |
202 | - `chart:render` - se o mixin executar um renderizador completo
203 | - `chart:destroy` - se o mixin excluir a instância do objeto de gráfico
204 | - `chart:update` - se o mixin executar uma atualização em vez de uma nova renderização
205 | - `labels:update` - se novos labels foram definidos
206 | - `xlabels:update` se novos xLabels foram definidos
207 | - `ylabels:update` - se novos yLabels foram definidos
208 |
209 | ### Solução de problemas
210 |
211 | O sistema de reatividade em seu estado atual não é **robusto**. Você terá vários problemas com isso, porque existem muitos casos de uso e maneiras de passar seus dados.
212 |
213 | #### Opções
214 |
215 | O objeto `options` não está atualmente implementado reativamente. Portanto, se você alterar dinamicamente as opções do gráfico, eles não serão reconhecidos pelo mixin. Se necessário, você pode criar um observador para destruir e renderizar novamente quando as opções do gráfico forem atualizadas.
216 |
217 | Se você estiver usando o mixin, precisará passar suas opções como um objeto chamado `options`. Isso é importante porque o mixin chamará o método `update ()` do Chart.js ou destruirá e renderizará um novo gráfico. Se o mixin renderizar um novo gráfico, ele chamará `this.renderChart(this.chartData, this.options)`.
218 |
219 | Mas, se você passar suas opções diretamente no seu gancho `mounted()`, elas serão destruídas.
220 |
221 | ::: danger Maneira errada
222 |
223 | ```js{7}
224 | import { Line, mixins } from 'vue-chartjs'
225 |
226 | export default {
227 | components: { Line }
228 | mixins: [mixins.reactiveProp],
229 | mounted () {
230 | this.renderChart(this.chartData, {responsive: true})
231 | }
232 | }
233 | ```
234 |
235 | :::
236 |
237 | ::: tip Maneira Certo
238 |
239 | ```js{7}
240 | import { Line, mixins } from 'vue-chartjs'
241 |
242 | export default {
243 | components: { Line }
244 | mixins: [mixins.reactiveProp],
245 | mounted () {
246 | this.renderChart(this.chartData, this.options)
247 | }
248 | }
249 | ```
250 |
251 | :::
252 |
253 | #### Próprio observador
254 |
255 | Se você transformar seus dados, mutação (em vez de enviar novos dados), é o melhor método, se você implementar seu próprio observador.
256 | Você pode chamar `this.$data._chart.update()` ou `this.renderChart()` de forma independente, dependendo de suas necessidades.
257 |
258 | Um observador simples seria:
259 |
260 | ```js
261 | watch: {
262 | chartData () {
263 | this.$data._chart.update()
264 | }
265 | }
266 | ```
267 |
268 | ## Exemplos
269 |
270 | ### Gráfico com props
271 |
272 | Seu objetivo deve ser criar componentes reutilizáveis do gráfico. Para esse fim, você deve utilizar as `props` do Vue.js para passar suas opções e seus dados do gráfico. Dessa forma, o próprio gráfico não possui uma opinião sobre a busca de dados e é apenas para apresentação.
273 |
274 | Primeiro, crie seu componente:
275 |
276 | ```js
277 | import { Line } from "vue-chartjs";
278 |
279 | export default {
280 | extends: Line,
281 | props: {
282 | chartdata: {
283 | type: Object,
284 | default: null
285 | },
286 | options: {
287 | type: Object,
288 | default: null
289 | }
290 | },
291 | mounted() {
292 | this.renderChart(this.chartdata, this.options);
293 | }
294 | };
295 | ```
296 |
297 | Depois disso, você pode adicionar o componente do gráfico a um componente pai:
298 |
299 | ```vue
300 |
301 | ```
302 |
303 | ### Gráfico com dados locais
304 |
305 | Você pode manipular os dados do gráfico diretamente em seu próprio componente do gráfico. Você só precisa passá-lo para o método `renderChart()`:
306 |
307 | ```js
308 | import { Bar } from "vue-chartjs";
309 |
310 | export default {
311 | extends: Bar,
312 | data: () => ({
313 | chartdata: {
314 | labels: ["January", "February"],
315 | datasets: [
316 | {
317 | label: "Data One",
318 | backgroundColor: "#f87979",
319 | data: [40, 20]
320 | }
321 | ]
322 | },
323 | options: {
324 | responsive: true,
325 | maintainAspectRatio: false
326 | }
327 | }),
328 |
329 | mounted() {
330 | this.renderChart(this.chartdata, this.options);
331 | }
332 | };
333 | ```
334 |
335 | ### Gráfico com dados da API
336 |
337 | Um padrão comum é usar uma API para recuperar seus dados. No entanto, existem algumas coisas para ter em mente. O problema mais comum é que você monta o componente do gráfico diretamente e transmite dados de uma chamada de API assíncrona. O problema dessa abordagem é que o Chart.js tenta renderizar seu gráfico e acessar os dados do gráfico de forma sincronizada, para que o gráfico seja montado antes que os dados da API cheguem.
338 |
339 | Para evitar isso, um simples `v-if` é a melhor solução.
340 |
341 | Crie seu componente de gráfico com um objeto de dados e opções, para que possamos transmitir nossos dados e opções de um componente de contêiner.
342 |
343 | **Chart.vue**
344 |
345 | ```js
346 | import { Line } from "vue-chartjs";
347 |
348 | export default {
349 | extends: Line,
350 | props: {
351 | chartdata: {
352 | type: Object,
353 | default: null
354 | },
355 | options: {
356 | type: Object,
357 | default: null
358 | }
359 | },
360 | mounted() {
361 | this.renderChart(this.chartdata, this.options);
362 | }
363 | };
364 | ```
365 |
366 | Em seguida, crie um componente de contêiner, que lida com a chamada da API ou a conexão vuex.
367 |
368 | **ChartContainer.vue**
369 |
370 | ```html {3}
371 |
372 |
373 |
374 |
375 |
376 |
377 |
399 | ```
400 |
401 | ### Gráfico com estilos dinâmicos
402 |
403 | Você pode definir `responsive: true` e passar um objeto de estilos que é aplicado como estilos embutidos para o exterior ``. Dessa forma, você pode alterar a altura e a largura do contêiner externo dinamicamente, o que não é o comportamento padrão do Chart.js. É melhor usar propriedades computadas para isso.
404 |
405 | ::: warning Aviso
406 | Você precisa definir `position: relative`
407 | :::
408 |
409 | ```html
410 |
411 |
412 |
413 | Increase height
414 |
415 |
416 |
417 |
439 | ```
440 |
441 | ### Personalizados / Novos Gráficos
442 |
443 | Às vezes, você precisa estender os gráficos Chart.js padrão. Existem muitos [exemplos](http://www.chartjs.org/docs/latest/developers/charts.html) sobre como estender e modificar os gráficos padrão. Ou você pode criar seu próprio tipo de gráfico.
444 |
445 | No `vue-chartjs`, você pode fazer isso da mesma maneira:
446 |
447 | ```js
448 | // 1. Importar Chart.js para que você possa usar o objeto Chart global
449 | import Chart from "chart.js";
450 | // 2. Importar o metodo `generateChart()` para criar o componente vue.
451 | import { generateChart } from "vue-chartjs";
452 |
453 | // 3. Estenda um dos gráficos padrão
454 | // http://www.chartjs.org/docs/latest/developers/charts.html
455 | Chart.defaults.LineWithLine = Chart.defaults.line;
456 | Chart.controllers.LineWithLine = Chart.controllers.line.extend({
457 | /* personalize sua magica aqui */
458 | });
459 |
460 | // 4. Gere o componente vue-chartjs
461 | // O primeiro argumento é o ID do gráfico, depois o tipo de gráfico.
462 | const CustomLine = generateChart("custom-line", "LineWithLine");
463 |
464 | // 5. Estender o component CustomLine assim como você faz com os gráficos vue-chartjs padrão.
465 |
466 | export default {
467 | extends: CustomLine,
468 | mounted() {
469 | // ....
470 | }
471 | };
472 | ```
473 |
474 | ## Recursos
475 |
476 | Aqui estão alguns recursos, como tutoriais, sobre como usar `vue-chartjs`:
477 |
478 | - [Usando vue-chartjs com WordPress](https://medium.com/@apertureless/wordpress-vue-and-chart-js-6b61493e289f)
479 | - [Crie gráficos impressionantes com Vue e Chart.js](https://hackernoon.com/creating-stunning-charts-with-vue-js-and-chart-js-28af584adc0a)
480 | - [Vamos construir um aplicativo web com Vue, Chart.js e uma API Parte I](https://hackernoon.com/lets-build-a-web-app-with-vue-chart-js-and-an-api-544eb81c4b44)
481 | - [Vamos construir um aplicativo web com Vue, Chart.js e uma API Parte II](https://hackernoon.com/lets-build-a-web-app-with-vue-chart-js-and-an-api-part-ii-39781b1d5acf)
482 | - [Construir um gráfico em tempo real com VueJS e Pusher](https://blog.pusher.com/build-realtime-chart-with-vuejs-pusher/)
483 |
--------------------------------------------------------------------------------
/website/src/pt-br/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | home: true
3 | heroImage: https://raw.githubusercontent.com/apertureless/vue-chartjs/main/website/src/images/vue-chartjs.png
4 | actionText: Começar →
5 | actionLink: /pt-br/guide/
6 | features:
7 | - title: Fácil
8 | details: Fácil para ambos, iniciantes e profissionais 🙌
9 | - title: Extensível
10 | details: Simples de usar, fácil de estender 💪
11 | - title: Poderoso
12 | details: Com todo o poder do chart.js 💯
13 | footer: MIT Licenciado | Copyright © 2018-presente Jakub Juszczak
14 | ---
15 |
--------------------------------------------------------------------------------
/website/src/ru/api/index.md:
--------------------------------------------------------------------------------
1 | # Справочник
2 |
3 | ## Свойства
4 |
5 | Существуют базовые свойства, определённые в компонентах, предоставленных `vue-chartjs`. Так как вы `extend`ите их, они *невидимы*, но вы можете переопределить их:
6 |
7 | | Свойство | Описание |
8 | |---|---|
9 | | width | ширина графика |
10 | | height | высота графика |
11 | | chart-id | id canvas-элемента |
12 | | css-classes | String с классами CSS для родительского элемента div |
13 | | styles | Object со стилями CSS для родительского элемента div |
14 | | plugins | Array с плагинами chartjs |
15 |
16 | ## События
17 |
18 | Если миксин `reactiveData` или `reactiveProp` привязан, будут вызываться следующие события:
19 |
20 | | Событие | Описание |
21 | |---|---|
22 | | `chart:render` | если миксин осуществляет полную перерисовку графика |
23 | | `chart:destroy` | если миксин удаляет экземпляр объекта графика |
24 | | `chart:update` | если миксин осуществеляет обновление графика вместо полной перерисовки |
25 | | `labels:update` | если установлены новые метки |
26 | | `xlabels:update` | если установлены новые метки по оси x |
27 | | `ylabels:update` | если установлены новые метки по оси y |
28 |
29 |
30 | ## Глобальные методы
31 | Глобальные методы, которые должны быть импортированы
32 |
33 | ### generateChart()
34 |
35 | - **Тип:** `Function`
36 | - **Аргументы:**: `chart-id`, `chart-type`
37 | - **Использование:**
38 |
39 | ```js
40 | import { generateChart } from 'vue-chartjs'
41 | // First argument is the chart-id, second the chart type.
42 | const CustomLine = generateChart('custom-line', 'LineWithLine')
43 | ```
44 |
45 | ## Методы экземпляра
46 |
47 | Методы экземпляра могут быть использованы внутри вашего графика-компонента
48 |
49 | ### generateLegend()
50 |
51 | Вспомогательная функция для генерации HTML-легенды
52 |
53 | - **Тип:** `Function`
54 | - **Использование:**
55 |
56 | ```js {11}
57 | import { Line } from 'vue-chartjs'
58 |
59 | export default {
60 | extends: Line,
61 | props: ['datasets', 'options']
62 | data: () => ({
63 | htmlLegend: null
64 | })
65 | mounted () {
66 | this.renderChart(this.datasets, this.options)
67 | this.htmlLegend = this.generateLegend()
68 | }
69 | }
70 |
71 | ```
72 |
73 | ### addPlugin()
74 |
75 | В Chart.js вы можете определить глобальные и встроенные плагины. Глобальные плагины без проблем работают с `vue-chartjs` как описано в [документации к Chart.js](http://www.chartjs.org/docs/latest/developers/plugins.html).
76 |
77 | Если вы хотите добавить встроенные плагины, `vue-chartjs` предоставляет вспомогательный метод `addPlugin()`
78 | Вам надо вызвать `addPlugin()` перед вызовом метода `renderChart()`.
79 |
80 | - **Тип:** `Function`
81 | - **Аргументы:**: `Array` плагинов
82 | - **Использование:**
83 |
84 | ```js
85 | mounted () {
86 | this.addPlugin({
87 | id: 'my-plugin',
88 | beforeInit: function (chart) {
89 | ....
90 | }
91 | })
92 | }
93 | ```
94 |
95 | ### renderChart()
96 |
97 | Создаёт экземпляр Chart.js и отрисовывает график.
98 |
99 | - **Тип:** `Function`
100 | - **Аргументы:**: `Chart Data`, `Chart Options`
101 | - **Использование:**
102 |
103 | ```js
104 | mounted () {
105 | this.renderChart({
106 | labels: ['Январь', 'Февраль'],
107 | datasets: [
108 | {
109 | label: 'Какие-то данные',
110 | backgroundColor: '#f87979',
111 | data: [40, 20]
112 | }
113 | ]},
114 | {
115 | responsive: true
116 | }
117 | )
118 | }
119 | ```
120 |
121 | ## Объект Chart.js
122 |
123 | Вы можете получить доступ к объекту Chart.js из вашего графика-компонента посредством `this.$data._chart`
124 |
125 | ## Canvas-элемент
126 |
127 | Вы можете получить доступ к canvas-элементу посредством `this.$refs.canvas`
128 |
--------------------------------------------------------------------------------
/website/src/ru/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | home: true
3 | heroImage: https://raw.githubusercontent.com/apertureless/vue-chartjs/main/website/src/images/vue-chartjs.png
4 | actionText: Начать →
5 | actionLink: /ru/guide/
6 | features:
7 | - title: Простота
8 | details: Просто как для новичков, так и для профессионалов 🙌
9 | - title: Расширяемость
10 | details: Просто использовать, легко расширять 💪
11 | - title: Могущество
12 | details: С полной силой chart.js 💯
13 | footer: MIT Licensed | Copyright © 2018-present Jakub Juszczak
14 | ---
15 |
--------------------------------------------------------------------------------
/website/src/zh-cn/api/index.md:
--------------------------------------------------------------------------------
1 | # 编码参考
2 |
3 | ## Props
4 |
5 | 这里有一些`vue-chartjs`提供的基本参数定义. 因为你是 `extend` 他们的, 所以他们是*不可见的*, 但是你可以覆盖他们:
6 |
7 | | 参数名 | 描述 |
8 | |---|---|
9 | | width | 图表宽度 |
10 | | height | 图表高度 |
11 | | chart-id | canvas的id |
12 | | css-classes | css类的字符串 |
13 | | styles | css 样式对象 |
14 | | plugins | chartjs 插件数组 |
15 |
16 | ## 事件
17 |
18 | 如果 `reactiveData` 或者 `reactiveProp` mixin 被附加, 下面事件将会被调用:
19 |
20 | | 事件 | 描述|
21 | |---|---|
22 | | `chart:render` | 如果 mixin 执行完全重绘 |
23 | | `chart:destroy` | 如果 mixin 删除图表对象实例 |
24 | | `chart:update` | 如果 mixin 执行更新而不是重绘 |
25 | | `labels:update` | 如果设置了新的labels |
26 | | `xlabels:update` | 如果设置了新的xLabels |
27 | | `ylabels:update` | 如果设置了新的yLabels |
28 |
29 |
30 | ## 全局方法
31 | 全局方法需要被引入才能使用.
32 |
33 | ### generateChart
34 |
35 | - **类型:** `Function`
36 | - **参数**: `chart-id`, `chart-type`
37 | - **使用:**
38 |
39 | ```js
40 | import { generateChart } from 'vue-chartjs'
41 | // 第一个参数是 图表id, 第二个参数是 图表类型.
42 | const CustomLine = generateChart('custom-line', 'LineWithLine')
43 | ```
44 |
45 | ## 实例方法
46 |
47 | 实例方法可以在你图表组件内部使用.
48 |
49 | ### generateLegend()
50 |
51 | 用来生成HTML说明的工具函数.
52 |
53 | - **类型:** `Function`
54 | - **参数**: `none`
55 | - **使用:**
56 |
57 | ```js {11}
58 | import { Line } from 'vue-chartjs'
59 |
60 | export default {
61 | extends: Line,
62 | props: ['datasets', 'options']
63 | data: () => ({
64 | htmlLegend: null
65 | })
66 | mounted () {
67 | this.renderChart(this.datasets, this.options)
68 | this.htmlLegend = this.generateLegend()
69 | }
70 | }
71 |
72 | ```
73 |
74 | ### addPlugin
75 |
76 | 在 Chart.js 你可以定义全局和内联插件. 全局插件在没有 `vue-chartjs`也可以工作. 就像这个文档[Chart.js docs](http://www.chartjs.org/docs/latest/developers/plugins.html) 描述的.
77 |
78 | 如果你需要添加内联插件, `vue-chartjs` 暴露出来了一个工具方法 `addPlugin()`
79 | 你可以在`renderChart()`方法前调用`addPlugin()`.
80 |
81 | - **类型:** `Function`
82 | - **参数**: `Array` 插件数组
83 | - **使用:**
84 |
85 | ```js
86 | mounted () {
87 | this.addPlugin({
88 | id: 'my-plugin',
89 | beforeInit: function (chart) {
90 | ....
91 | }
92 | })
93 | }
94 | ```
95 |
96 | ### renderChart()
97 |
98 | 创建一个 Chart.js 实例, 并渲染图表
99 |
100 | - **类型:** `Function`
101 | - **参数**: `Chart Data`, `Chart Options`
102 | - **使用:**
103 |
104 | ```js
105 | mounted () {
106 | this.renderChart({
107 | labels: ['January', 'February'],
108 | datasets: [
109 | {
110 | label: 'Data One',
111 | backgroundColor: '#f87979',
112 | data: [40, 20]
113 | }
114 | ]},
115 | {
116 | responsive: true
117 | }
118 | )
119 | }
120 | ```
121 |
122 | ## Chart.js 对象
123 |
124 | 你可以在你的图表组件里, 通过 `this.$data._chart` 访问 Chart.js 对象
125 |
126 | ## Canvas
127 |
128 | 你可以通过 `this.$refs.canvas` 访问 canvas
129 |
--------------------------------------------------------------------------------
/website/src/zh-cn/guide/index.md:
--------------------------------------------------------------------------------
1 | # 起步
2 |
3 | **vue-chartjs** 是 Vue 对于 [Chart.js](https://github.com/chartjs/Chart.js) 的封装. 你可以很简单的创建可复用的图表组件.
4 |
5 | ## 介绍
6 |
7 | `vue-chartjs` 让你在 Vue 中能更好的使用 Chart.js . 非常适合想要尽快启动和运行简单图表的人
8 |
9 | 它抽象了一些简单的逻辑, 但是也暴露了 Chart.js 对象, 提供了极大的灵活性.
10 |
11 | ## 安装
12 |
13 | ### NPM
14 |
15 | 你可以在 `npm` 下安装 `vue-chartjs`. 当然, 你也需要在项目中安装 `chart.js` 依赖. 因为 `Chart.js` 是一个 [peerDependency](https://docs.npmjs.com/files/package.json#peerdependencies). 这种方式你可以完全控制 Chart.js 的版本
16 |
17 | `yarn add vue-chartjs chart.js` or `npm install vue-chartjs chart.js --save`
18 |
19 | ::: tip
20 | 如果你使用的是 vue 1.x 版本, 请使用 `legacy` 标签. 然而, Vue 1 所支持的版本不再维护了.
21 |
22 | `yarn add vue-chartjs@legacy`
23 | :::
24 |
25 | ### 浏览器
26 |
27 | 你也可以直接在浏览器中使用 `vue-chartjs`.
28 | 先添加 `Chart.js` 脚本, 再添加 `vue-chartjs` 脚本.
29 |
30 | ```html
31 |
32 |
33 | ```
34 | ## 整合
35 |
36 | `Chart.js` 将所有可用的图表类型, 都导出为命名组件, 并可以直接导入它们. 这些组件都是普通的 Vue 组件, 然而, 你需要`扩展`它.
37 |
38 | `vue-chartjs` 的想法是提供容易使用的组件, 并且具有最大限度的灵活性和扩展性. 要实现这一点, 你需要创建你自己的 *Chart Component* 并通过 `vue-chartjs` 提供的组件来扩展它.
39 |
40 | 这样,Chart组件中的方法和逻辑就可以合并到您自己的图表组件中.
41 |
42 | ## 创建你自己的第一个图表
43 |
44 | 你需要引入一个基本图表然后扩展它. 这为处理不同数据时提供了更大的灵活性. 你可以封装你的组件以及使用props来处理数据, 或者你可以直接在组件里输入他们. 当然, 如果那样做, 你的组件就无法复用了.
45 |
46 | 你可以引入整个项目或者每个模块单独引用. 之后你需要使用`extends:`或者 `mixins:[]`. 然后在 `mounted()` 中调用 `this.renderChart()`. 这将创建你的图表实例.
47 |
48 | ```js{1,4,6}
49 | import { Bar } from 'vue-chartjs'
50 |
51 | export default {
52 | extends: Bar,
53 | mounted () {
54 | this.renderChart(data, options)
55 | }
56 | }
57 | ```
58 |
59 | :::tip
60 | 你可以使用 `extends: Bar` 或者 `mixins: [Bar]`
61 | :::
62 |
63 | `this.renderChart()` 方法由 `Bar` 组件提供, 接收两个对象参数.第一个是你的图表数据, 第二个是配置对象.
64 |
65 | 在这个文档中查看你需要提供的对象结构 [Chart.js docs](http://www.chartjs.org/docs/latest/#creating-a-chart) .
66 |
67 | ### Vue 单文件组件
68 |
69 | 文档中很多例子都是基于javascript文件 而不是 `.vue` 文件. 这是因为你大多数只需要`
85 |
86 |
88 | ```
89 |
90 | ::: danger 不要使用Template标签
91 | 不要在你的 `.vue` 文件中引入 `
` 标签. Vue **无法** 合并模板.如果你添加了一个空的 `` 标签, Vue 将会从你的主键里获取模板, 而不会从你 `extend` 中获取, 这将导致页面为空并报错.
92 | :::
93 |
94 | ## 更新 Charts
95 |
96 | 如果你修改了数据集, Chart.js 是不会提供实时更新的. 当然, `vue-chartjs` 提供了两个 mixins 来实现.
97 |
98 | - `reactiveProp`
99 | - `reactiveData`
100 |
101 | 这两个mixins其实实现的是相同的功能. 大多数时间你将会使用`reactiveProp`. 它扩展了图表组件的逻辑, 并自动创建名为 `chartData` 的`props`参数, 并为这个参数添加`vue watch`. 当数据改变, 如果数据在数据集中改变, 它将调用`update()`; 如果添加了新的数据集, 它将调用`renderChart()`.
102 |
103 | `reactiveData` 创建一个本地的`chartData`变量, 不是`props`参数! 以及创建一个对这个变量的 `watcher`. 如果你需要单一目的的图表, 以及在图表组件中进行API调用的时候, 这将非常有用.
104 |
105 | ### 例子
106 |
107 | **LineChart.js**
108 | ```javascript
109 | import { Line, mixins } from 'vue-chartjs'
110 | const { reactiveProp } = mixins
111 |
112 | export default {
113 | extends: Line,
114 | mixins: [reactiveProp],
115 | props: ['options'],
116 | mounted () {
117 | // this.chartData 在 mixin 创建.
118 | // 如果你需要替换 options , 请创建本地的 options 对象
119 | this.renderChart(this.chartData, this.options)
120 | }
121 | }
122 | ```
123 |
124 | **RandomChart.vue**
125 |
126 | ```html
127 |
128 |
129 |
130 | Randomize
131 |
132 |
133 |
134 |
172 |
173 |
179 | ```
180 |
181 | ::: danger 限制
182 |
183 | [Caveats](https://vuejs.org/v2/guide/list.html#Caveats)
184 | [Change-Detection-Caveats](https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats)
185 | [vm.$watch](https://vuejs.org/v2/api/#vm-watch)
186 |
187 | :::
188 |
189 |
190 | ### 事件
191 |
192 | 如果你的数据改变, 响应式的 mixins 将会触发事件. 你能监听他们通过在图表组件上使用 `v:on`. 下列是可用的事件:
193 |
194 | - `chart:render` - 如果 mixin 执行完全重绘
195 | - `chart:destroy` - 如果 mixin 删除图表对象实例
196 | - `chart:update` - 如果 mixin 执行更新而不是重绘
197 | - `labels:update` - 如果设置了新的labels
198 | - `xlabels:update` 如果设置了新的xLabels
199 | - `ylabels:update` - 如果设置了新的yLabels
200 |
201 |
202 | ### 故障排查
203 |
204 | 响应式系统, 它当前状态是**不健全的**. 你将会遇到一些问题, 因为有很多用例和方式来传递你的数据.
205 |
206 | #### Options
207 |
208 | `options` 对象不是响应式的. 所以如果你动态改变图表的配置, 他们将无法被 mixin 识别.
209 |
210 | 如果你正在使用 mixin , 你需要使用`options`来传递你的配置. 这是非常重要的, 因为 mixin 将调用 chart.js 的 `update()` 方法 或者 销毁并渲染一个新的图表. 如果 mixin 渲染一个新的图表, 它将调用`this.renderChart(this.chartData, this.options)`.
211 |
212 | 但是如果你在`mounted()`传递你的配置, 它们将直接被遗弃.
213 |
214 | ::: danger 错误的方式
215 | ```js {7}
216 | import { Line, mixins } from 'vue-chartjs'
217 |
218 | export default {
219 | components: { Line }
220 | mixins: [mixins.reactiveProp],
221 | mounted () {
222 | this.renderChart(this.chartData, {responsive: true})
223 | }
224 | }
225 | ```
226 | :::
227 |
228 | ::: tip 正确的方式
229 | ```js {7}
230 | import { Line, mixins } from 'vue-chartjs'
231 |
232 | export default {
233 | components: { Line }
234 | mixins: [mixins.reactiveProp],
235 | mounted () {
236 | this.renderChart(this.chartData, this.options)
237 | }
238 | }
239 | ```
240 |
241 | :::
242 |
243 | #### 自己的监视器
244 |
245 | 如果你对你的数据进行大量更改(而不是推新的数据), 那么最好的方式是创建自己的 watcher.
246 | 你可以自己调用 `this.$data._chart.update()` 或者 `this.renderChart()` 来实现, 当然这些完全取决于你自己.
247 |
248 | 一个简单的监视器将会是这样:
249 |
250 | ```js
251 | watch: {
252 | chartData () {
253 | this.$data._chart.update()
254 | }
255 | }
256 | ```
257 |
258 | ## 例子
259 |
260 | ### 使用props的图表
261 |
262 | 你的目标因该是创建可复用的图表组件. 出于这个目的, 你应该利用 Vue.js 的`props` 来传递你的配置和图表数据. 这种方式, 图表自己不用关心, 关于提取数据, 只用来展示.
263 |
264 | 首先, 创建你的组件
265 |
266 | ```js
267 | import { Line } from 'vue-chartjs'
268 |
269 | export default {
270 | extends: Line,
271 | props: {
272 | chartdata: {
273 | type: Object,
274 | default: null
275 | },
276 | options: {
277 | type: Object,
278 | default: null
279 | }
280 | },
281 | mounted () {
282 | this.renderChart(this.chartdata, this.options)
283 | }
284 | }
285 | ```
286 |
287 | 然后, 你可以把你的组件添加到父组件里
288 |
289 | ```html
290 |
291 | ```
292 |
293 | ### 图表使用本地数据
294 |
295 | 你可以直接在你自己的图表组件里处理你的图表数据. 你只需要把它传递到 `renderChart()`.
296 |
297 | ```js
298 | import { Bar } from 'vue-chartjs'
299 |
300 | export default {
301 | extends: Bar,
302 | data: () => ({
303 | chartdata: {
304 | labels: ['January', 'February'],
305 | datasets: [
306 | {
307 | label: 'Data One',
308 | backgroundColor: '#f87979',
309 | data: [40, 20]
310 | }
311 | ]
312 | },
313 | options: {
314 | responsive: true,
315 | maintainAspectRatio: false
316 | }
317 | }),
318 |
319 | mounted () {
320 | this.renderChart(this.chartdata, this.options)
321 | }
322 | }
323 | ```
324 |
325 | ### Chart使用API的数据
326 |
327 | 使用API获取数据是一种常见模式. 然而, 这里有一些问题需要记住. 最常见的问题是, 你直接安装你的图表, 将异步API回调的数据传递进去. 这种方法导致的问题是, chart.js 试图去渲染你的图表, 访问图表数据, 但是你的API回调是异步的. 所以你图表在你数据到达前安装.
328 |
329 | 防止这个问题, 一个 `v-if` 即可.
330 |
331 | 创建你的图表组件通过一个数据参数和一个配置参数, 所以我们可以从一个容器组件中传递我们的数据和配置.
332 |
333 | **Chart.vue**
334 |
335 | ```js
336 | import { Line } from 'vue-chartjs'
337 |
338 | export default {
339 | extends: Line,
340 | props: {
341 | chartdata: {
342 | type: Object,
343 | default: null
344 | },
345 | options: {
346 | type: Object,
347 | default: null
348 | }
349 | },
350 | mounted () {
351 | this.renderChart(this.chartdata, this.options)
352 | }
353 | }
354 | ```
355 |
356 | 然后创建一个容器组件, 用来处理你的API回调和vuex连接.
357 | **ChartContainer.vue**
358 |
359 | ```html {4}
360 |
361 |
362 |
366 |
367 |
368 |
369 |
391 | ```
392 |
393 | ### Chart的动态样式
394 |
395 | 你可以设置 `responsive: true` 然后传递到 styles 对象, 这被当做内联样式应用于外层div. 这种方式你可以动态改变外层容器的高度和宽度, 这并不是chart.js 的默认行为. 使用计算属性可以很好的完成.
396 |
397 | ::: warning
398 | 你需要设置 `position: relative`
399 | :::
400 |
401 | ```html
402 |
403 |
404 |
405 | Increase height
406 |
407 |
408 |
409 |
431 | ```
432 |
433 | ### 自定义/新的图表
434 |
435 | 有时候你需要扩展Chart.js默认的图表. 这里有许多[例子](http://www.chartjs.org/docs/latest/developers/charts.html), 来教你如何扩展和修改默认的图表, 或者创建自己的图表类型.
436 |
437 | 在 `vue-chartjs`, 你可以使用同样的方式来做到这一点
438 |
439 | ```js
440 | // 1. 引入Chart.js, 你可以使用全局的图表对象
441 | import Chart from 'chart.js'
442 | // 2. 引入 `generateChart()`方法创建vue组件.
443 | import { generateChart } from 'vue-chartjs'
444 |
445 | // 3. 扩展一个默认图表
446 | // http://www.chartjs.org/docs/latest/developers/charts.html
447 | Chart.defaults.LineWithLine = Chart.defaults.line;
448 | Chart.controllers.LineWithLine = Chart.controllers.line.extend({ /* 自定义 */})
449 |
450 | // 4. 生成 vue-chartjs 组件
451 | // 第一个参数是 图表id, 第二个参数是 图表类型.
452 | const CustomLine = generateChart('custom-line', 'LineWithLine')
453 |
454 | // 5. 像使用默认的vue-chartjs图表一样, 扩展自定义组件
455 |
456 | export default {
457 | extends: CustomLine,
458 | mounted () {
459 | // ....
460 | }
461 | }
462 | ```
463 |
464 | ## 资源
465 |
466 | 你可以在这里找到一些资源,比如关于如何使用`vue-chartjs`的教程
467 |
468 | - [Using vue-chartjs with WordPress](https://medium.com/@apertureless/wordpress-vue-and-chart-js-6b61493e289f)
469 | - [Create stunning Charts with Vue and Chart.js](https://hackernoon.com/creating-stunning-charts-with-vue-js-and-chart-js-28af584adc0a)
470 | - [Let’s Build a Web App with Vue, Chart.js and an API Part I](https://hackernoon.com/lets-build-a-web-app-with-vue-chart-js-and-an-api-544eb81c4b44)
471 | - [Let’s Build a Web App with Vue, Chart.js and an API Part II](https://hackernoon.com/lets-build-a-web-app-with-vue-chart-js-and-an-api-part-ii-39781b1d5acf)
472 | - [Build a realtime chart with VueJS and Pusher](https://blog.pusher.com/build-realtime-chart-with-vuejs-pusher/)
473 |
--------------------------------------------------------------------------------
/website/src/zh-cn/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | home: true
3 | heroImage: https://raw.githubusercontent.com/apertureless/vue-chartjs/main/website/src/images/vue-chartjs.png
4 | actionText: 起步 →
5 | actionLink: /zh-cn/guide/
6 | features:
7 | - title: 简单
8 | details: 适合初学者和专业人士 🙌
9 | - title: 扩展性
10 | details: 使用简单, 扩展方便 💪
11 | - title: 强大
12 | details: 拥有 chart.js 的全部功能 💯
13 | footer: MIT Licensed | Copyright © 2018-present Jakub Juszczak
14 | ---
15 |
--------------------------------------------------------------------------------