mirror of
https://github.com/simon987/music-graph-ui.git
synced 2025-04-10 05:56:42 +00:00
Add input bar, add node menu
This commit is contained in:
parent
7ba2dfbdff
commit
0e428548a5
6
music_graph/package-lock.json
generated
6
music_graph/package-lock.json
generated
@ -5942,7 +5942,8 @@
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "3.7.0",
|
||||
"resolved": "",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz",
|
||||
"integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
@ -6172,8 +6173,7 @@
|
||||
"lodash": {
|
||||
"version": "4.17.11",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
|
||||
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
|
||||
},
|
||||
"lodash.camelcase": {
|
||||
"version": "4.3.0",
|
||||
|
@ -15,6 +15,7 @@
|
||||
"d3-force": "^2.0.1",
|
||||
"d3-path": "^1.0.7",
|
||||
"element-ui": "^2.7.2",
|
||||
"lodash": "^4.17.11",
|
||||
"vue": "^2.6.10",
|
||||
"vue-resource": "^1.5.1",
|
||||
"vue-router": "^3.0.2"
|
||||
|
@ -1,4 +1,5 @@
|
||||
import * as d3 from 'd3'
|
||||
import icons from './icons'
|
||||
|
||||
export const nodeUtils = {
|
||||
getNodeType: function (labels) {
|
||||
@ -13,6 +14,21 @@ export const nodeUtils = {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: export somewhere else
|
||||
const arc = function (radius, itemNumber, itemCount, width) {
|
||||
itemNumber = itemNumber - 1
|
||||
|
||||
const startAngle = ((2 * Math.PI) / itemCount) * itemNumber
|
||||
const endAngle = startAngle + (2 * Math.PI) / itemCount
|
||||
const innerRadius = Math.max(radius + 8, 20)
|
||||
return d3.arc()
|
||||
.innerRadius(innerRadius)
|
||||
.outerRadius(innerRadius + width)
|
||||
.startAngle(startAngle)
|
||||
.endAngle(endAngle)
|
||||
.padAngle(0.09)
|
||||
}
|
||||
|
||||
export function MusicGraph(data) {
|
||||
const width = window.innerWidth - 7
|
||||
const height = window.innerHeight - 7
|
||||
@ -24,7 +40,7 @@ export function MusicGraph(data) {
|
||||
this.links = []
|
||||
this._originSet = false
|
||||
|
||||
this.svg = d3.select('body')
|
||||
this.svg = d3.select('#mm')
|
||||
.append('svg')
|
||||
.attr('width', width)
|
||||
.attr('height', height)
|
||||
@ -33,6 +49,20 @@ export function MusicGraph(data) {
|
||||
this.container.attr('transform', d3.event.transform)
|
||||
}
|
||||
|
||||
this.dismiss = () => {
|
||||
this.menu.remove()
|
||||
this.nodes.forEach(d => {
|
||||
d.menu = null
|
||||
})
|
||||
}
|
||||
|
||||
this.svg.append('rect')
|
||||
.attr('width', width)
|
||||
.attr('height', height)
|
||||
.classed('dismiss-rect', true)
|
||||
.style('fill', 'none')
|
||||
.on('mousedown', this.dismiss)
|
||||
|
||||
this.svg.append('rect')
|
||||
.attr('width', width)
|
||||
.attr('height', height)
|
||||
@ -50,6 +80,8 @@ export function MusicGraph(data) {
|
||||
.attr('id', 'nodes')
|
||||
this.container.append('g')
|
||||
.attr('id', 'labels')
|
||||
this.container.append('g')
|
||||
.attr('id', 'menu')
|
||||
|
||||
this.dragStarted = (d) => {
|
||||
if (!d3.event.active) {
|
||||
@ -116,12 +148,62 @@ export function MusicGraph(data) {
|
||||
}
|
||||
|
||||
this.nodeDbClick = (d) => {
|
||||
if (this.expandedNodes.has(d.id)) {
|
||||
if (d.menu) {
|
||||
return
|
||||
}
|
||||
|
||||
this.expandedNodes.add(d.id)
|
||||
this.expandArtist(d.mbid)
|
||||
this.svg.classed('menu-mode', true)
|
||||
d.menu = true
|
||||
|
||||
// TODO: Move this somewhere else V V V
|
||||
d.fx = d.x
|
||||
d.fy = d.y
|
||||
const items = [
|
||||
{idx: 0, icon: icons.expand},
|
||||
{idx: 1, icon: icons.release},
|
||||
{idx: 2, icon: icons.hash},
|
||||
{idx: 3, icon: icons.guitar}
|
||||
]
|
||||
|
||||
const tr = `translate(${d.x},${d.y})`
|
||||
this.menu = this.container.select('#menu')
|
||||
.selectAll('g')
|
||||
.data(items)
|
||||
.enter()
|
||||
.append('g')
|
||||
.classed('menu-item', true)
|
||||
.attr('transform', tr)
|
||||
|
||||
this.menu
|
||||
.append('path')
|
||||
.attr('d', item => arc(35, item.idx, items.length, 1)())
|
||||
.on('mouseover', d => {
|
||||
this.menu.classed('hover', item => item.idx === d.idx)
|
||||
})
|
||||
.on('mouseout', () => this.menu.classed('hover', false))
|
||||
.transition()
|
||||
.duration(200)
|
||||
.attr('d', item => arc(35, item.idx, items.length, 30)())
|
||||
|
||||
const angleOffset = items.length === 3 ? 3.72 : 3.927 // Don't ask
|
||||
this.menu
|
||||
.append('g')
|
||||
.html(d => d.icon)
|
||||
.classed('menu-icon', true)
|
||||
.attr('transform', d =>
|
||||
`translate(${40 * Math.cos(2 * Math.PI * d.idx / items.length + angleOffset) - 10},
|
||||
${40 * Math.sin(2 * Math.PI * d.idx / items.length + angleOffset) - 10})`
|
||||
)
|
||||
.transition()
|
||||
.duration(250)
|
||||
.attr('transform', d =>
|
||||
`translate(
|
||||
${57 * Math.cos(2 * Math.PI * d.idx / items.length + angleOffset) - 10},
|
||||
${57 * Math.sin(2 * Math.PI * d.idx / items.length + angleOffset) - 10})`
|
||||
)
|
||||
// ^ ^ ^
|
||||
|
||||
d3.event.preventDefault()
|
||||
}
|
||||
|
||||
this.simulation = d3.forceSimulation()
|
||||
@ -147,9 +229,35 @@ export function MusicGraph(data) {
|
||||
.attr('y', d => d.y)
|
||||
})
|
||||
|
||||
/**
|
||||
* Add nodes to the graph
|
||||
*/
|
||||
this.addNode = function (newNode, relations) {
|
||||
// Convert {id, id} relation to {node, node}
|
||||
if (this.nodeById.has(newNode.id)) {
|
||||
return
|
||||
}
|
||||
this.nodeById.set(newNode.id, newNode)
|
||||
newNode.x = width / 2
|
||||
newNode.y = height / 2
|
||||
|
||||
let linksToAdd = relations
|
||||
.filter(rel => this.nodeById.has(rel.source) && this.nodeById.has(rel.target))
|
||||
.map(({weight, source, target}) => ({
|
||||
source: this.nodeById.get(source),
|
||||
target: this.nodeById.get(target),
|
||||
weight: weight
|
||||
}))
|
||||
|
||||
// Update source/targetLinks
|
||||
for (const {source, target} of linksToAdd) {
|
||||
source.sourceLinks.add(target.id)
|
||||
target.targetLinks.add(source.id)
|
||||
}
|
||||
|
||||
this.nodes.push(newNode)
|
||||
this.links.push(...linksToAdd)
|
||||
|
||||
this._update()
|
||||
}
|
||||
|
||||
this.addNodes = function (newNodes, relations, originId) {
|
||||
// Update node map, ignore existing nodes
|
||||
let nodesToAdd = []
|
||||
@ -191,7 +299,7 @@ export function MusicGraph(data) {
|
||||
this.nodes.push(...nodesToAdd)
|
||||
this.links.push(...linksToAdd)
|
||||
|
||||
if (!this._originSet) {
|
||||
if (!this._originSet && originId) {
|
||||
this._setOrigin()
|
||||
this._originSet = true
|
||||
}
|
||||
@ -238,8 +346,8 @@ export function MusicGraph(data) {
|
||||
(1.2 / d.weight) * (94 * this.expandedNodes.size))
|
||||
)
|
||||
)
|
||||
this.simulation
|
||||
.restart()
|
||||
|
||||
this.simulation.alphaTarget(0.01).restart()
|
||||
|
||||
// Add new links
|
||||
this.link = this.container.select('#links')
|
||||
@ -269,6 +377,7 @@ export function MusicGraph(data) {
|
||||
.on('mouseover', this.nodeHover)
|
||||
.on('mouseout', this.nodeOut)
|
||||
.on('dblclick', this.nodeDbClick)
|
||||
.on('contextmenu', this.nodeDbClick)
|
||||
this.node = nodeEnter.merge(this.node)
|
||||
|
||||
// Add new labels
|
||||
@ -323,7 +432,7 @@ export function MusicGraph(data) {
|
||||
|
||||
this.expandArtist = function (mbid) {
|
||||
// todo use http client
|
||||
d3.json('https://mm.simon987.net/api/artist/related/' + mbid)
|
||||
d3.json('http://localhost:3030/artist/related/' + mbid)
|
||||
.then((r) => {
|
||||
this.originArtist = r.artists.find(a => a.mbid === mbid)
|
||||
|
||||
@ -343,6 +452,24 @@ export function MusicGraph(data) {
|
||||
})
|
||||
}
|
||||
|
||||
this.addArtistByName = function (name) {
|
||||
// todo use http client
|
||||
d3.json('http://localhost:3030/artist/related_by_name/' + name)
|
||||
.then((r) => {
|
||||
const node = r.artists.find(a => a.name === name)
|
||||
|
||||
this.addNode({
|
||||
id: node.id,
|
||||
mbid: node.mbid,
|
||||
name: node.name,
|
||||
listeners: node.listeners,
|
||||
type: nodeUtils.getNodeType(node.labels),
|
||||
sourceLinks: new Set(),
|
||||
targetLinks: new Set()
|
||||
}, r.relations)
|
||||
})
|
||||
}
|
||||
|
||||
this._update()
|
||||
this.setupKeyBindings()
|
||||
}
|
||||
|
5
music_graph/src/MusicGraphApi.js
Normal file
5
music_graph/src/MusicGraphApi.js
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
export default function MusicGraphApi() {
|
||||
let a = 0
|
||||
console.log(a)
|
||||
}
|
63
music_graph/src/components/AlbumCarousel.vue
Normal file
63
music_graph/src/components/AlbumCarousel.vue
Normal file
@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<div>
|
||||
<figure
|
||||
v-for="release in releases"
|
||||
v-show="current === release.mbid"
|
||||
v-bind:key="release.mbid"
|
||||
>
|
||||
<figure>
|
||||
<img
|
||||
alt=""
|
||||
width="128"
|
||||
height="128"
|
||||
v-bind:src="'http://localhost:3030/cover/' + release.mbid"
|
||||
>
|
||||
<figcaption>{{release.name}} ({{release.year}})</figcaption>
|
||||
</figure>
|
||||
</figure>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
let data = {
|
||||
current: '',
|
||||
index: 0
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'AlbumCarousel',
|
||||
props: ['releases', 'interval'],
|
||||
data() {
|
||||
return data
|
||||
},
|
||||
mounted() {
|
||||
setInterval(() => {
|
||||
this.tick()
|
||||
}, Number(this.interval))
|
||||
},
|
||||
watch: {
|
||||
releases: () => {
|
||||
data.index = 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
tick() {
|
||||
if (data.index === this.releases.length - 1) {
|
||||
data.index = 0
|
||||
}
|
||||
|
||||
data.index += 1
|
||||
data.current = this.releases[data.index].mbid
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
figure {
|
||||
text-align: center;
|
||||
margin: 0 0 10px 0;
|
||||
max-width: 300px;
|
||||
}
|
||||
</style>
|
@ -4,38 +4,38 @@
|
||||
<span>{{artist.name}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<ImageCarousel
|
||||
v-bind:sources="artistInfo.covers"
|
||||
<AlbumCarousel
|
||||
style="float: left"
|
||||
v-bind:releases="artistInfo.releases"
|
||||
interval="750" />
|
||||
<span>Listeners: {{artist.listeners}}</span>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import ImageCarousel from './ImageCarousel'
|
||||
import AlbumCarousel from './AlbumCarousel'
|
||||
|
||||
let data = {
|
||||
artistInfo: {
|
||||
releases: [],
|
||||
covers: []
|
||||
releases: []
|
||||
}
|
||||
}
|
||||
|
||||
function reloadInfo(artist) {
|
||||
Vue.http.get('https://mm.simon987.net/api/artist/details/' + artist.mbid)
|
||||
Vue.http.get('http://localhost:3030/artist/details/' + artist.mbid)
|
||||
.then(response => {
|
||||
response.json().then(info => {
|
||||
info.covers = info.releases.map(mbid => 'https://mm.simon987.net/api/cover/' + mbid)
|
||||
|
||||
data.artistInfo = info
|
||||
data.artistInfo.releases = data.artistInfo.releases.slice(0, 2)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'ArtistInfo',
|
||||
components: {ImageCarousel},
|
||||
components: {AlbumCarousel},
|
||||
props: ['artist'],
|
||||
watch: {
|
||||
artist: reloadInfo
|
||||
|
@ -1,5 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<div id="mm"></div>
|
||||
<InputBar v-on:query="onQuery($event)"></InputBar>
|
||||
<ArtistInfo v-bind:artist="hoverArtist"/>
|
||||
</div>
|
||||
</template>
|
||||
@ -7,18 +9,27 @@
|
||||
<script>
|
||||
import ArtistInfo from './ArtistInfo'
|
||||
import {MusicGraph} from '../MusicGraph'
|
||||
import InputBar from './InputBar'
|
||||
|
||||
let data = {
|
||||
hoverArtist: undefined
|
||||
hoverArtist: undefined,
|
||||
mm: undefined
|
||||
}
|
||||
|
||||
let mm = new MusicGraph(data)
|
||||
mm.expandArtist('66fc5bf8-daa4-4241-b378-9bc9077939d2')
|
||||
|
||||
export default {
|
||||
components: {ArtistInfo},
|
||||
components: {InputBar, ArtistInfo},
|
||||
data() {
|
||||
return data
|
||||
},
|
||||
methods: {
|
||||
onQuery: function (e) {
|
||||
console.log(e)
|
||||
this.mm.addArtistByName(e)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.mm = new MusicGraph(data)
|
||||
this.mm.addArtistByName('Tool')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -34,6 +45,8 @@ export default {
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
/* Pan mode */
|
||||
@ -49,6 +62,10 @@ export default {
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
svg.menu-mode .dismiss-rect {
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
svg.pan-mode {
|
||||
box-sizing: border-box;
|
||||
border: 5px red solid;
|
||||
@ -92,7 +109,6 @@ export default {
|
||||
/* Label */
|
||||
svg .label {
|
||||
text-anchor: middle;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
svg.hover .label:not(.selected) {
|
||||
@ -102,4 +118,34 @@ export default {
|
||||
body {
|
||||
background: #E7EDEB;
|
||||
}
|
||||
|
||||
/* test */
|
||||
|
||||
#menu .menu-item {
|
||||
cursor: pointer;
|
||||
fill: orange;
|
||||
}
|
||||
|
||||
#menu .menu-item.hover {
|
||||
fill: darkorange;
|
||||
}
|
||||
|
||||
#menu .menu-item.hover text {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#menu .menu-item text {
|
||||
text-anchor: middle;
|
||||
fill: white;
|
||||
}
|
||||
|
||||
#menu .menu-icon {
|
||||
fill: black;
|
||||
stroke: black;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
text {
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,51 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<img
|
||||
alt=""
|
||||
width="96"
|
||||
height="96"
|
||||
v-show="currentSrc === url"
|
||||
v-bind:src="url"
|
||||
v-bind:key="url"
|
||||
v-for="url in sources"
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
let data = {
|
||||
currentSrc: '',
|
||||
index: 0
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'ImageCarousel',
|
||||
props: ['sources', 'interval'],
|
||||
data() {
|
||||
return data
|
||||
},
|
||||
mounted() {
|
||||
setInterval(() => {
|
||||
this.tick()
|
||||
}, Number(this.interval))
|
||||
},
|
||||
watch: {
|
||||
sources: () => {
|
||||
data.index = 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
tick() {
|
||||
if (data.index === this.sources.length - 1) {
|
||||
data.index = 0
|
||||
}
|
||||
|
||||
data.index += 1
|
||||
data.currentSrc = this.sources[data.index]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
45
music_graph/src/components/InputBar.vue
Normal file
45
music_graph/src/components/InputBar.vue
Normal file
@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<div class="bar-wrapper">
|
||||
<el-input
|
||||
v-model="query"
|
||||
@keyup.enter.native="onSubmit"
|
||||
placeholder="Add nodes"
|
||||
></el-input>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as _ from 'lodash'
|
||||
|
||||
export default {
|
||||
name: 'InputBar',
|
||||
data: () => {
|
||||
return {
|
||||
query: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
query: _.debounce(function () {
|
||||
// todo: autocomplete
|
||||
|
||||
}, 125)
|
||||
},
|
||||
methods: {
|
||||
onSubmit: function () {
|
||||
this.$emit('query', this.query)
|
||||
this.query = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.bar-wrapper {
|
||||
text-align: center;
|
||||
padding: 2em 0;
|
||||
}
|
||||
|
||||
.el-input {
|
||||
width: 50%;
|
||||
}
|
||||
</style>
|
47
music_graph/src/icons.js
Normal file
47
music_graph/src/icons.js
Normal file
@ -0,0 +1,47 @@
|
||||
const icons = {
|
||||
expand: '<svg viewBox="0 0 55 55" width="30px" height="30px" transform="translate(-7,0)">\n' +
|
||||
'<path d="M49,0c-3.309,0-6,2.691-6,6c0,1.035,0.263,2.009,0.726,2.86l-9.829,9.829C32.542,17.634,30.846,17,29,17\n' +
|
||||
'\ts-3.542,0.634-4.898,1.688l-7.669-7.669C16.785,10.424,17,9.74,17,9c0-2.206-1.794-4-4-4S9,6.794,9,9s1.794,4,4,4\n' +
|
||||
'\tc0.74,0,1.424-0.215,2.019-0.567l7.669,7.669C21.634,21.458,21,23.154,21,25s0.634,3.542,1.688,4.897L10.024,42.562\n' +
|
||||
'\tC8.958,41.595,7.549,41,6,41c-3.309,0-6,2.691-6,6s2.691,6,6,6s6-2.691,6-6c0-1.035-0.263-2.009-0.726-2.86l12.829-12.829\n' +
|
||||
'\tc1.106,0.86,2.44,1.436,3.898,1.619v10.16c-2.833,0.478-5,2.942-5,5.91c0,3.309,2.691,6,6,6s6-2.691,6-6c0-2.967-2.167-5.431-5-5.91\n' +
|
||||
'\tv-10.16c1.458-0.183,2.792-0.759,3.898-1.619l7.669,7.669C41.215,39.576,41,40.26,41,41c0,2.206,1.794,4,4,4s4-1.794,4-4\n' +
|
||||
'\ts-1.794-4-4-4c-0.74,0-1.424,0.215-2.019,0.567l-7.669-7.669C36.366,28.542,37,26.846,37,25s-0.634-3.542-1.688-4.897l9.665-9.665\n' +
|
||||
'\tC46.042,11.405,47.451,12,49,12c3.309,0,6-2.691,6-6S52.309,0,49,0z M11,9c0-1.103,0.897-2,2-2s2,0.897,2,2s-0.897,2-2,2\n' +
|
||||
'\tS11,10.103,11,9z M6,51c-2.206,0-4-1.794-4-4s1.794-4,4-4s4,1.794,4,4S8.206,51,6,51z M33,49c0,2.206-1.794,4-4,4s-4-1.794-4-4\n' +
|
||||
'\ts1.794-4,4-4S33,46.794,33,49z M29,31c-3.309,0-6-2.691-6-6s2.691-6,6-6s6,2.691,6,6S32.309,31,29,31z M47,41c0,1.103-0.897,2-2,2\n' +
|
||||
'\ts-2-0.897-2-2s0.897-2,2-2S47,39.897,47,41z M49,10c-2.206,0-4-1.794-4-4s1.794-4,4-4s4,1.794,4,4S51.206,10,49,10z"/>\n' +
|
||||
'</svg>',
|
||||
release: '<svg viewBox="0 0 217.465 217.465" width="30px" height="30px" transform="translate(-1,-5)">\n' +
|
||||
'<path d="M108.732,152.869c-24.337,0-44.137-19.8-44.137-44.137c0-24.337,19.8-44.137,44.137-44.137\n' +
|
||||
'\tc24.337,0,44.137,19.8,44.137,44.137C152.869,133.07,133.07,152.869,108.732,152.869z M108.732,75.505\n' +
|
||||
'\tc-18.322,0-33.227,14.906-33.227,33.228c0,18.322,14.906,33.227,33.227,33.227c18.322,0,33.227-14.906,33.227-33.227\n' +
|
||||
'\tC141.96,90.411,127.054,75.505,108.732,75.505z M108.732,129.388c-11.408,0-20.655-9.248-20.655-20.656\n' +
|
||||
'\tc0-11.408,9.248-20.655,20.655-20.655c11.408,0,20.655,9.248,20.655,20.655C129.388,120.14,120.14,129.388,108.732,129.388z\n' +
|
||||
'\t M108.732,0C48.777,0,0,48.778,0,108.732s48.777,108.732,108.732,108.732s108.732-48.777,108.732-108.732S168.687,0,108.732,0z\n' +
|
||||
'\t M108.732,46.79c-34.155,0-61.942,27.787-61.942,61.942c0,2.762-2.239,5-5,5s-5-2.238-5-5c0-39.669,32.273-71.942,71.942-71.942\n' +
|
||||
'\tc2.761,0,5,2.238,5,5S111.494,46.79,108.732,46.79z M108.732,26.306c-45.45,0-82.427,36.977-82.427,82.427c0,2.762-2.239,5-5,5\n' +
|
||||
'\ts-5-2.238-5-5c0-50.964,41.462-92.427,92.427-92.427c2.761,0,5,2.238,5,5S111.494,26.306,108.732,26.306z"/>\n' +
|
||||
'</svg>',
|
||||
guitar: '<svg width="30px" height="30px" viewBox="0 0 481.684 481.683" transform="translate(-3,-3)">' +
|
||||
'<path d="M469.783,14.968c0.312-0.693,0.412-1.196,0.292-1.491c-2.701-6.424-4.66,2.016-24.221-8.874\n' +
|
||||
'\t\t\tc-19.548-10.893-24.63,0.966-24.63,0.966s-19.411,36.914-39.833,51.327c-20.435,14.413-21.428,12.381-22.586,24.95\n' +
|
||||
'\t\t\tc-1.167,12.565-5.438,16.646-5.438,16.646l0.309,0.331l-105.384,97.529c-0.1-6.39-6.159-6.073-6.159-6.073\n' +
|
||||
'\t\t\tc-24.964-11.68-19.266-18.578-6.664-46.466c12.595-27.89-4.482-33.897-4.482-33.897s-33.654,44.781-56.961,44.24\n' +
|
||||
'\t\t\tc-23.309-0.545-23.898,7.456-23.898,7.456s17.294,56.719-40.287,66.014c-21.516,3.468-37.612,8.636-49.333,13.74\n' +
|
||||
'\t\t\tc-2.761,1.146-5.464,2.433-8.109,3.851c-13.604,7.062-18.905,13.101-18.905,13.101l0.167,0.156c-1.515,1.379-3.005,2.797-4.45,4.3\n' +
|
||||
'\t\t\tc-43.687,45.3-35.432,124.143,18.456,176.11c53.884,51.965,132.977,57.362,176.664,12.066c3.65-3.787,6.869-7.786,9.744-11.941\n' +
|
||||
'\t\t\tl0.024,0.031c15.018-16.967,19.787-55.803,19.787-55.803s4.685-49.344,35.374-43.112c30.688,6.243,30.824-13.168,30.824-13.168\n' +
|
||||
'\t\t\ts-1.639-36.853,12.748-46.338c14.391-9.481,16.562-23.104-2.22-15.485c-18.791,7.622-30.068,14.375-47.557,0.377\n' +
|
||||
'\t\t\tc-10.251-8.211-12.295-20.478-12.251-29.224l113.555-109.09c2.513-1.28,6.816-2.831,13.785-3.422\n' +
|
||||
'\t\t\tc12.58-1.07,10.548-2.082,25.115-22.406c14.559-20.324,51.623-39.455,51.623-39.455s11.891-4.993,1.143-24.627\n' +
|
||||
'\t\t\tC467.719,22.125,470.849,17.533,469.783,14.968z"/></svg>',
|
||||
hash: '<svg viewBox="0 0 281.465 281.465" width="28px" height="28px" transform="translate(-4,0)">\n' +
|
||||
'<path d="M273.661,114.318V67.035h-45.558L236.886,0h-47.69l-8.783,67.035h-60.084L129.113,0H81.425L72.64,67.035H7.804v47.283\n' +
|
||||
'\th58.649l-6.904,52.791H7.804v47.289h45.559l-8.784,67.066h47.687l8.787-67.066h60.083l-8.786,67.066h47.691l8.783-67.066h64.836\n' +
|
||||
'\tv-47.289h-58.647l6.901-52.791H273.661z M167.326,167.109h-60.084l6.9-52.791h60.082L167.326,167.109z"/>\n' +
|
||||
'</svg>'
|
||||
|
||||
}
|
||||
|
||||
export default icons
|
Loading…
x
Reference in New Issue
Block a user