diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2020-02-18 19:31:11 +0900 |
|---|---|---|
| committer | syuilo <Syuilotan@yahoo.co.jp> | 2020-02-18 19:31:11 +0900 |
| commit | 0508d5f643aeb2ee0cbd1d95c37bc031ad7eb27e (patch) | |
| tree | 816a5261d8d833500bcab0b1b1e82c179022f350 /src/client/widgets/activity.chart.vue | |
| parent | Implement featured note injection (diff) | |
| download | sharkey-0508d5f643aeb2ee0cbd1d95c37bc031ad7eb27e.tar.gz sharkey-0508d5f643aeb2ee0cbd1d95c37bc031ad7eb27e.tar.bz2 sharkey-0508d5f643aeb2ee0cbd1d95c37bc031ad7eb27e.zip | |
Add activity widget
Diffstat (limited to 'src/client/widgets/activity.chart.vue')
| -rw-r--r-- | src/client/widgets/activity.chart.vue | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/src/client/widgets/activity.chart.vue b/src/client/widgets/activity.chart.vue new file mode 100644 index 0000000000..0278e02ae7 --- /dev/null +++ b/src/client/widgets/activity.chart.vue @@ -0,0 +1,108 @@ +<template> +<svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`" @mousedown.prevent="onMousedown"> + <polyline + :points="pointsNote" + fill="none" + stroke-width="1" + stroke="#41ddde"/> + <polyline + :points="pointsReply" + fill="none" + stroke-width="1" + stroke="#f7796c"/> + <polyline + :points="pointsRenote" + fill="none" + stroke-width="1" + stroke="#a1de41"/> + <polyline + :points="pointsTotal" + fill="none" + stroke-width="1" + stroke="#555" + stroke-dasharray="2 2"/> +</svg> +</template> + +<script lang="ts"> +import Vue from 'vue'; +import i18n from '../i18n'; + +function dragListen(fn) { + window.addEventListener('mousemove', fn); + window.addEventListener('mouseleave', dragClear.bind(null, fn)); + window.addEventListener('mouseup', dragClear.bind(null, fn)); +} + +function dragClear(fn) { + window.removeEventListener('mousemove', fn); + window.removeEventListener('mouseleave', dragClear); + window.removeEventListener('mouseup', dragClear); +} + +export default Vue.extend({ + i18n, + props: ['data'], + data() { + return { + viewBoxX: 147, + viewBoxY: 60, + zoom: 1, + pos: 0, + pointsNote: null, + pointsReply: null, + pointsRenote: null, + pointsTotal: null + }; + }, + created() { + for (const d of this.data) { + d.total = d.notes + d.replies + d.renotes; + } + + this.render(); + }, + methods: { + render() { + const peak = Math.max.apply(null, this.data.map(d => d.total)); + if (peak != 0) { + const data = this.data.slice().reverse(); + this.pointsNote = data.map((d, i) => `${(i * this.zoom) + this.pos},${(1 - (d.notes / peak)) * this.viewBoxY}`).join(' '); + this.pointsReply = data.map((d, i) => `${(i * this.zoom) + this.pos},${(1 - (d.replies / peak)) * this.viewBoxY}`).join(' '); + this.pointsRenote = data.map((d, i) => `${(i * this.zoom) + this.pos},${(1 - (d.renotes / peak)) * this.viewBoxY}`).join(' '); + this.pointsTotal = data.map((d, i) => `${(i * this.zoom) + this.pos},${(1 - (d.total / peak)) * this.viewBoxY}`).join(' '); + } + }, + onMousedown(e) { + const clickX = e.clientX; + const clickY = e.clientY; + const baseZoom = this.zoom; + const basePos = this.pos; + + // 動かした時 + dragListen(me => { + let moveLeft = me.clientX - clickX; + let moveTop = me.clientY - clickY; + + this.zoom = baseZoom + (-moveTop / 20); + this.pos = basePos + moveLeft; + if (this.zoom < 1) this.zoom = 1; + if (this.pos > 0) this.pos = 0; + if (this.pos < -(((this.data.length - 1) * this.zoom) - this.viewBoxX)) this.pos = -(((this.data.length - 1) * this.zoom) - this.viewBoxX); + + this.render(); + }); + } + } +}); +</script> + +<style lang="scss" scoped> +svg { + display: block; + padding: 16px; + width: 100%; + box-sizing: border-box; + cursor: all-scroll; +} +</style> |