想做图标,但是很麻烦
This commit is contained in:
parent
1425b173d8
commit
f0ca5b6496
|
@ -7,4 +7,19 @@
|
|||
svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.back {
|
||||
fill: white;
|
||||
}
|
||||
.front {
|
||||
fill: #096E11;
|
||||
}
|
||||
pad-icon[type="awoken-count"][number="full"][special] .back {
|
||||
fill: #FFFFD4;
|
||||
}
|
||||
pad-icon[type="awoken-count"][number="full"][special] .front {
|
||||
fill: #F3DC69;
|
||||
}
|
||||
pad-icon[type="awoken-count"][latent] .front {
|
||||
fill: #378DE8;
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<svg id="图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 123 75">
|
||||
<style>
|
||||
.back {
|
||||
fill: #FFFFD4;
|
||||
}
|
||||
.front {
|
||||
fill: #F3DC69;
|
||||
}
|
||||
</style>
|
||||
<defs>
|
||||
<filter id="inset-shadow" x="-50%" y="-50%" width="200%" height="200%" name="inset-shadow">
|
||||
<feComponentTransfer in="SourceAlpha">
|
||||
<feFuncA tableValues="1 0" type="table"/>
|
||||
</feComponentTransfer>
|
||||
<feGaussianBlur stdDeviation="1" result="blur"/>
|
||||
<feFlood flood-color="white" />
|
||||
<feComposite in2="blur" operator="in"/>
|
||||
<feOffset dx="0" dy="3"/>
|
||||
<feComposite in2="SourceAlpha" operator="in" result="offsetblur-bottom"/>
|
||||
<feFlood flood-color="black" />
|
||||
<feComposite in2="blur" operator="in"/>
|
||||
<feOffset dx="0" dy="-3"/>
|
||||
<feComposite in2="SourceAlpha" operator="in" result="offsetblur-top"/>
|
||||
<feMerge>
|
||||
<feMergeNode in="SourceGraphic"/>
|
||||
<feMergeNode in="offsetblur-bottom"/>
|
||||
<feMergeNode in="offsetblur-top"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
<filter id="out-shadow" x="-50%" y="-50%" width="200%" height="200%" name="inset-shadow">
|
||||
<feComponentTransfer in="SourceAlpha">
|
||||
<feFuncA tableValues="0 1" type="table"/>
|
||||
</feComponentTransfer>
|
||||
<feGaussianBlur stdDeviation="1" result="blur"/>
|
||||
<feOffset dx="0" dy="3"/>
|
||||
<feComposite in2="SourceAlpha" operator="out" result="offsetblur"/>
|
||||
<feMerge>
|
||||
<feMergeNode in="SourceGraphic"/>
|
||||
<feMergeNode in="offsetblur"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
<symbol id="awoken-count-bg" viewBox="0 0 36 40">
|
||||
<g>
|
||||
<circle class="back" filter="url(#out-shadow)" cx="18" cy="16" r="16"/>
|
||||
<circle class="front" filter="url(#inset-shadow)" cx="18" cy="16" r="13"/>
|
||||
</g>
|
||||
</symbol>
|
||||
<image width="123" height="40" xlink:href="../../../CTFX/Desktop/%E6%9C%AA%E5%91%BD%E5%90%8D-3.png"/>
|
||||
<g id="bg-enable-be-assist">
|
||||
<circle class="back" filter="url(#out-shadow)" cx="23" cy="49" r="16"/>
|
||||
<circle class="front" filter="url(#inset-shadow)" cx="23" cy="49" r="13"/>
|
||||
</g>
|
||||
<g id="bg-latent">
|
||||
<circle fill="white" filter="url(#out-shadow)" cx="60" cy="49" r="16"/>
|
||||
<circle fill="#378DE8" filter="url(#inset-shadow)" cx="60" cy="49" r="13"/>
|
||||
</g>
|
||||
<g id="bg-unable-be-assist">
|
||||
<circle fill="white" filter="url(#out-shadow)" cx="103" cy="49" r="16"/>
|
||||
<circle fill="#096E11" filter="url(#inset-shadow)" cx="103" cy="49" r="13"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.4 KiB |
|
@ -1,19 +1,26 @@
|
|||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const mime = require('mime'); //需要安装
|
||||
const sizeOf = require('image-size'); //需要安装
|
||||
const { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom'); //需要安装
|
||||
const xmlFormatter = require('xml-formatter');
|
||||
const xmlFormatter = require('xml-formatter'); //需要安装
|
||||
const sharp = require('sharp'); //需要安装
|
||||
|
||||
const directory = './awokens';
|
||||
const files = fs.readdirSync(directory);
|
||||
const svgNS = 'http://www.w3.org/2000/svg';
|
||||
|
||||
class Icon {
|
||||
constructor(file, dir) {
|
||||
this.fileName = file;
|
||||
this.directory = dir;
|
||||
this.buffer = fs.readFileSync(this.path());
|
||||
this.size = sizeOf(this.buffer);
|
||||
this.sharp = sharp(this.buffer);
|
||||
this.init();
|
||||
}
|
||||
async init() {
|
||||
this.buffer = await this.sharp.metadata();
|
||||
const {data, info} = await this.sharp.webp({ nearLossless : true}) //近似无损,而非绝对无损
|
||||
.toBuffer({ resolveWithObject: true });
|
||||
this.webpBuffer = data;
|
||||
this.webpInfo = info;
|
||||
}
|
||||
path() {
|
||||
return path.join(this.directory, this.fileName);
|
||||
|
@ -21,45 +28,63 @@ class Icon {
|
|||
base64() {
|
||||
return `data:${mime.getType(this.fileName)};base64,${this.buffer.toString('base64')}`;
|
||||
}
|
||||
webpBase64() {
|
||||
return `data:${mime.getType('webp')};base64,${this.webpBuffer.toString('base64')}`;
|
||||
}
|
||||
}
|
||||
const iconArr = [];
|
||||
for (const file of files)
|
||||
{
|
||||
const icon = new Icon(file, directory);
|
||||
iconArr.push(icon);
|
||||
}
|
||||
iconArr.sort((a,b)=>{
|
||||
function nameNum(fileName){return parseInt(/^\d+/.exec(fileName)[0])}
|
||||
return (nameNum(a.fileName) - nameNum(b.fileName)) || //先判断数字
|
||||
(a.fileName.length - b.fileName.length); //然后判断文件名长度
|
||||
});
|
||||
|
||||
const svgNS = 'http://www.w3.org/2000/svg';
|
||||
|
||||
//const dt = new DOMImplementation().createDocumentType('svg:svg', '-//W3C//DTD SVG 1.1//EN', 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd');
|
||||
//const svg = new DOMImplementation().createDocument(svgNS, 'svg', dt);
|
||||
const svg = new DOMImplementation().createDocument(svgNS, 'svg');
|
||||
|
||||
for (const icon of iconArr)
|
||||
{
|
||||
console.log('正在处理 %s', icon.fileName);
|
||||
const symbol = svg.createElement('symbol');
|
||||
const parseName = path.parse(icon.fileName);
|
||||
const regRes = /^(\d+)(.*)$/ig.exec(parseName.name);
|
||||
let aid = regRes ? `${parseInt(regRes[1])}${regRes[2]}` : parseName.name;
|
||||
symbol.setAttribute('id', `awoken-${aid}`);
|
||||
symbol.setAttribute('viewBox', `0 0 32 32`);
|
||||
svg.documentElement.appendChild(symbol);
|
||||
const image = svg.createElement('image');
|
||||
image.setAttribute('width', icon.size.width);
|
||||
image.setAttribute('height', icon.size.height);
|
||||
image.setAttribute('href', icon.base64());
|
||||
symbol.appendChild(image);
|
||||
async function main({directory, idPre, svgFilename}) {
|
||||
const files = fs.readdirSync(directory);
|
||||
|
||||
const iconArr = [];
|
||||
for (const file of files)
|
||||
{
|
||||
const icon = new Icon(file, directory);
|
||||
await icon.init();
|
||||
iconArr.push(icon);
|
||||
}
|
||||
iconArr.sort((a,b)=>{
|
||||
function nameNum(fileName){return parseInt(/^\d+/.exec(fileName)[0] || 0)}
|
||||
return (nameNum(a.fileName) - nameNum(b.fileName)) || //先判断数字
|
||||
(a.fileName.length - b.fileName.length); //然后判断文件名长度
|
||||
});
|
||||
const svgDoc = new DOMImplementation().createDocument(svgNS, 'svg');
|
||||
|
||||
for (const icon of iconArr)
|
||||
{
|
||||
console.log('正在处理 %s %s', directory, icon.fileName);
|
||||
const symbol = svgDoc.createElement('symbol');
|
||||
const parseName = path.parse(icon.fileName);
|
||||
|
||||
const regRes = /^(\d+)(.*)$/ig.exec(parseName.name);
|
||||
let aid = regRes ? `${parseInt(regRes[1])}${regRes[2]}` : parseName.name;
|
||||
symbol.setAttribute('id', `${idPre}-${aid}`);
|
||||
symbol.setAttribute('viewBox', `0 0 32 32`);
|
||||
svgDoc.documentElement.appendChild(symbol);
|
||||
const image = svgDoc.createElement('image');
|
||||
image.setAttribute('width', icon.webpInfo.width);
|
||||
image.setAttribute('height', icon.webpInfo.height);
|
||||
image.setAttribute('href', icon.webpBase64());
|
||||
|
||||
symbol.appendChild(image);
|
||||
}
|
||||
const serialized = new XMLSerializer().serializeToString(svgDoc);
|
||||
const formattedXml = xmlFormatter(serialized, {
|
||||
indentation: '\t',
|
||||
filter: (node) => node.type !== 'Comment',
|
||||
collapseContent: true,
|
||||
lineSeparator: '\n'
|
||||
});
|
||||
fs.writeFileSync(svgFilename, formattedXml);
|
||||
}
|
||||
const serialized = new XMLSerializer().serializeToString(svg);
|
||||
const formattedXml = xmlFormatter(serialized, {
|
||||
indentation: '\t',
|
||||
filter: (node) => node.type !== 'Comment',
|
||||
collapseContent: true,
|
||||
lineSeparator: '\n'
|
||||
});
|
||||
fs.writeFileSync('../icon-awoken.svg', formattedXml);
|
||||
|
||||
const tasks = [
|
||||
{directory: './awokens', idPre: 'awoken', svgFilename: '../icon-awoken.svg'},
|
||||
{directory: './types', idPre: 'type', svgFilename: '../icon-type.svg'},
|
||||
];
|
||||
|
||||
tasks.forEach(main);
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"@xmldom/xmldom": "^0.8.2",
|
||||
"image-size": "^1.0.2",
|
||||
"mime": "^3.0.0",
|
||||
"opencc-js": "^1.0.4",
|
||||
"sharp": "^0.30.7",
|
||||
"xml-formatter": "^2.6.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,22 +114,26 @@ class PadIcon extends HTMLElement {
|
|||
// Specify observed attributes so that
|
||||
// attributeChangedCallback will work
|
||||
static get observedAttributes() {
|
||||
return ['iid','type','lang'];
|
||||
return [
|
||||
'type', //图标类型
|
||||
'number', //编号或数字,必须是数字
|
||||
'lang', //英语、中文特殊图标的设定
|
||||
'icon-name',//子图标名称
|
||||
'icon-value',//子图标的值
|
||||
'full',//觉醒打满
|
||||
'special',//是否是特殊颜色
|
||||
];
|
||||
}
|
||||
#iid = 0;
|
||||
#number = 0;
|
||||
#type = "awoken";
|
||||
get iid() { this.#iid; }
|
||||
/**
|
||||
* @param {string | number} x
|
||||
*/
|
||||
set iid(x) {
|
||||
this.setAttribute('iid', x);
|
||||
this.#iid = x;
|
||||
get number() { this.#number; }
|
||||
set number(x) {
|
||||
const number = Number(x);
|
||||
if (Number.isNaN(number)) throw new Error('传入的 number 不是数字!');
|
||||
this.setAttribute('number', number);
|
||||
this.#number = number;
|
||||
}
|
||||
get type() { this.#type; }
|
||||
/**
|
||||
* @param {string} x
|
||||
*/
|
||||
set type(x) {
|
||||
this.setAttribute('type', x);
|
||||
this.#type = x;
|
||||
|
@ -154,24 +158,48 @@ class PadIcon extends HTMLElement {
|
|||
this.update();
|
||||
}
|
||||
attributeChangedCallback(name, oldValue, newValue) { //自定义标签属性改变
|
||||
if (name == 'iid') this.#iid = parseInt(newValue);
|
||||
if (name == 'number') {
|
||||
const number = Number(newValue);
|
||||
this.#number = Number.isNaN(number) ? 0 : number;
|
||||
}
|
||||
if (name == 'type') this.#type = newValue;
|
||||
this.update();
|
||||
}
|
||||
update() {
|
||||
let iid = this.#iid || 0;
|
||||
let number = this.#number;
|
||||
const type = this.#type;
|
||||
const lang = this.getAttribute('lang') || currentLanguage.i18n;
|
||||
const shadow = this.shadowRoot;
|
||||
const use = shadow.querySelector('use');
|
||||
const svg = shadow.querySelector('svg');
|
||||
const use = svg.querySelector('use');
|
||||
switch (type) {
|
||||
case 'awoken': {
|
||||
if (/^(?:en|ko)/.test(lang) && [40,46,47,48].includes(iid)) iid += '-en'; //英文不一样的觉醒
|
||||
if (/^(?:zh)/.test(lang) && [46,47].includes(iid)) iid += '-zh'; //中文不一样的觉醒
|
||||
use.setAttribute("href",`images/icon-awoken.svg#awoken-${iid}`);
|
||||
if (/^(?:en|ko)/.test(lang) && [40,46,47,48].includes(number)) number += '-en'; //英文不一样的觉醒
|
||||
if (/^(?:zh)/.test(lang) && [46,47].includes(number)) number += '-zh'; //中文不一样的觉醒
|
||||
use.setAttribute("href",`images/icon-awoken.svg#awoken-${number}`);
|
||||
break;
|
||||
}
|
||||
case 'type': {
|
||||
if (/^(?:en|ko)/.test(lang) && [9,12].includes(number)) number += '-en'; //英文不一样的类型
|
||||
use.setAttribute("href",`images/icon-type.svg#type-${number}`);
|
||||
break;
|
||||
}
|
||||
case 'awoken-count': {
|
||||
use.setAttribute("href",`images/icon-awoken-count.svg#awoken-count-bg`);
|
||||
const text = svg.appendChild(document.createElementNS(svgNS, 'text'));
|
||||
const iconName = this.getAttribute('icon-name');
|
||||
svg.setAttribute("icon-name", iconName);
|
||||
//awoken,latent,8-latent
|
||||
//full,enable-assist-full,latent-full,8-latent,8-latent-full
|
||||
|
||||
const full = this.getAttribute('full') != null;
|
||||
const special = this.getAttribute('special') != null;
|
||||
text.textContent = full ? '★' : number;
|
||||
text.setAttribute("x", "50%");
|
||||
text.setAttribute("y", "50%");
|
||||
text.setAttribute("class", "number");
|
||||
break;
|
||||
}
|
||||
case 'type':
|
||||
case 'latent':
|
||||
case 'badge':
|
||||
case 'attr':
|
||||
|
|
Loading…
Reference in New Issue