Skip to content

Commit a1f4b0c

Browse files
committed
新增demo
1 parent e25c8ef commit a1f4b0c

File tree

12 files changed

+968
-286
lines changed

12 files changed

+968
-286
lines changed
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
const fs = require('fs');
2+
const path = require('path');
3+
const Spritesmith = require('spritesmith');
4+
const { stringifyRequest } = require('loader-utils');
5+
var valueParser = require('postcss-value-parser');
6+
7+
module.exports = function (source) {
8+
9+
let outputName = new Date().getTime() + '_smith.png';
10+
// 清除css中的注释
11+
const cleanSource = source.replace(/\/\*[\w\W]*\*\//g, '')
12+
13+
let imgs = cleanSource.match(/url\(.+_sprite.+\)/g);
14+
15+
const callback = this.async();
16+
17+
imgs = imgs.map(item => path.resolve(this.context, item.replace(/(url\(.)|(.\))/g, '')));
18+
19+
Spritesmith.run({ src: imgs }, async (err, result) => {
20+
if (err) throw err;
21+
22+
// 雪碧图尺寸
23+
const imgInfo = result.properties;
24+
25+
// 子图片的偏移、尺寸信息
26+
const coord = {};
27+
28+
for (key in result.coordinates) {
29+
let newKey = key.match(/\w+_sprite.+/)[0];
30+
coord[newKey] = result.coordinates[key];
31+
delete result.coordinates[key];
32+
}
33+
34+
const emitFile = (name) => {
35+
return new Promise((resolve) => {
36+
fs.mkdir(this.context + '/sprites', { recursive: true }, (err) => {
37+
if (err) {
38+
throw (err);
39+
}
40+
fs.writeFileSync(path.resolve(this.context, 'sprites', name), result.image);
41+
resolve();
42+
});
43+
});
44+
}
45+
// 当前目录生成雪碧图
46+
await emitFile(outputName);
47+
48+
let parsedValue = valueParser(cleanSource);
49+
50+
// 包含所有需要转化的css块
51+
let blocks = {};
52+
53+
// 找到当前css块的范围
54+
function findCurrentDeclare(currentIndex) {
55+
let beginIndex;
56+
57+
let endIndex;
58+
59+
parsedValue.walk(node => {
60+
if (/\{/.test(node.value) && node.sourceIndex < currentIndex) {
61+
beginIndex = node.sourceIndex;
62+
}
63+
if (endIndex === undefined && /\}/.test(node.value) && node.sourceIndex > currentIndex) {
64+
endIndex = node.sourceIndex;
65+
}
66+
});
67+
if (beginIndex === undefined || endIndex === undefined) throw new Error(`css code error!`);
68+
return {
69+
beginIndex,
70+
endIndex,
71+
currentIndex
72+
};
73+
}
74+
75+
parsedValue.walk(node => {
76+
if (node.value === 'url' && /_sprite.+/.test(node.nodes[0].value)) {
77+
blocks[node.sourceIndex] = findCurrentDeclare(node.sourceIndex);
78+
blocks[node.sourceIndex].url = node.nodes[0].value.match(/\w+_sprite.+/)[0];
79+
}
80+
});
81+
82+
// 转换
83+
for (const key in blocks) {
84+
let bgLineStart = 0;
85+
let bgLineEnd = 0;
86+
let bgszLineStart = 0;
87+
let bgszLineEnd = 0;
88+
let width;
89+
let height;
90+
let x;
91+
let y;
92+
let ratio;
93+
const item = blocks[key];
94+
// 找到background所在行
95+
parsedValue.walk(node => {
96+
if (blocks[key].beginIndex <= node.sourceIndex && blocks[key].endIndex >= node.sourceIndex) {
97+
if (bgLineStart !== 0 && bgLineEnd !== 0) return;
98+
99+
if (bgLineStart === 0 && node.value === 'background') {
100+
bgLineStart = node.sourceIndex;
101+
return;
102+
}
103+
104+
if (bgLineStart !== 0 && /;/.test(node.value)) {
105+
bgLineEnd = node.sourceIndex;
106+
return;
107+
}
108+
109+
}
110+
});
111+
// 找到background-size所在行
112+
parsedValue.walk(node => {
113+
if (blocks[key].beginIndex <= node.sourceIndex && blocks[key].endIndex >= node.sourceIndex) {
114+
if (bgszLineStart !== 0 && bgszLineEnd !== 0) return;
115+
116+
if (bgszLineStart === 0 && node.value === 'background-size') {
117+
bgszLineStart = node.sourceIndex;
118+
return;
119+
}
120+
121+
if (bgszLineStart !== 0 && /;/.test(node.value)) {
122+
bgszLineEnd = node.sourceIndex;
123+
return;
124+
}
125+
126+
}
127+
});
128+
129+
// 处理 background-size
130+
parsedValue.walk(node => {
131+
if (bgszLineStart <= node.sourceIndex && bgszLineEnd >= node.sourceIndex) {
132+
133+
// 若background-size只有一个px
134+
if (width === undefined && /px;/.test(node.value)) {
135+
ratio = node.value.match(/\d+/)[0] / coord[item.url].width;
136+
width = imgInfo.width * ratio + 'px ';
137+
height = imgInfo.height * ratio + 'px;';
138+
node.value = width + height;
139+
return;
140+
}
141+
if (width === undefined && /px/.test(node.value)) {
142+
ratio = node.value.match(/\d+/)[0] / coord[item.url].width;
143+
width = imgInfo.width * ratio + 'px';
144+
node.value = width;
145+
return;
146+
}
147+
if (width !== undefined && height === undefined && /px;/.test(node.value)) {
148+
height = imgInfo.height * ratio + 'px;';
149+
node.value = height;
150+
return;
151+
}
152+
153+
154+
}
155+
});
156+
// 处理 background
157+
if (ratio) {
158+
parsedValue.walk(node => {
159+
if (bgLineStart <= node.sourceIndex && bgLineEnd >= node.sourceIndex) {
160+
161+
if (x === undefined && /px/.test(node.value)) {
162+
x = - coord[item.url].x * ratio + Number(node.value.match(/-?\d+/)[0]) + 'px';
163+
node.value = x;
164+
return;
165+
}
166+
if (x !== undefined && y === undefined && /px;/.test(node.value)) {
167+
y = - coord[item.url].y * ratio + Number(node.value.match(/-?\d+/)[0]) + 'px;';
168+
node.value = y;
169+
return;
170+
}
171+
if (x !== undefined && y === undefined && /px/.test(node.value)) {
172+
y = - coord[item.url].y * ratio + Number(node.value.match(/-?\d+/)[0]) + 'px';
173+
node.value = y;
174+
return;
175+
}
176+
}
177+
});
178+
}
179+
}
180+
callback(null, parsedValue.toString().replace(/url\(.+_sprite.+\)/g, `url(${stringifyRequest(this.context, './sprites/' + outputName)})`));
181+
});
182+
183+
}

demo/resource/demo1_sprite.png

3.92 KB
Loading

demo/resource/demo2_sprite.png

3.37 KB
Loading

demo/resource/index.html

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<!--
2+
* @Descripttion:
3+
* @Author: sunft
4+
* @Date: 2020-05-14 10:52:55
5+
* @LastEditTime: 2020-05-22 14:13:22
6+
-->
7+
<!DOCTYPE html>
8+
<html lang="en">
9+
10+
<head>
11+
<meta charset="UTF-8">
12+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
13+
<title>demo</title>
14+
</head>
15+
16+
<body>
17+
<div id='root'></div>
18+
</body>
19+
20+
</html>

demo/resource/index.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* @Descripttion:
3+
* @Author: sunft
4+
* @Date: 2020-05-14 13:18:03
5+
* @LastEditTime: 2020-05-22 11:35:52
6+
*/
7+
require('./style.css');
8+
9+
document.getElementById('root').innerHTML =
10+
`<h3 class="text_center">this is a demo</h3>
11+
<div class="my_content">
12+
<div class="my_bg_1"></div>
13+
<div class="my_bg_2"></div>
14+
</div>`
15+
10.8 KB
Loading
10.8 KB
Loading

demo/resource/style.css

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
.my_bg_1{
2+
height: 100px;
3+
width: 100px;
4+
background: url('./demo1_sprite.png');
5+
background-size: 100px;
6+
border: 1px solid #ddd;
7+
display: inline-block;
8+
}
9+
10+
.my_bg_2{
11+
height: 100px;
12+
width: 100px;
13+
background: url('./demo2_sprite.png') no-repeat -20px -20px;
14+
background-size: 150px;
15+
border: 1px solid #ddd;
16+
display: inline-block;
17+
margin-left: 20px;
18+
}
19+
20+
.my_content{
21+
display: flex;
22+
justify-content: center;
23+
}
24+
25+
.text_center{
26+
text-align: center;
27+
}

demo/webpack.config.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* @Descripttion:
3+
* @Author: sunft
4+
* @Date: 2020-03-24 11:19:44
5+
* @LastEditTime: 2020-05-22 14:58:48
6+
*/
7+
const path = require("path");
8+
const webpack = require("webpack");
9+
const HtmlWebpackPlugin = require('html-webpack-plugin');
10+
module.exports = {
11+
entry: {
12+
index: './resource/index.js',
13+
},
14+
output: {
15+
filename: '[name].bundle.js',
16+
path: path.resolve(__dirname, 'dist')
17+
},
18+
module: {
19+
rules: [
20+
{
21+
test: /\.(png|jpe?g|gif)$/i,
22+
loader: 'file-loader',
23+
options: {
24+
outputPath: 'images',
25+
},
26+
},
27+
{
28+
test: /\.css$/i,
29+
use: [
30+
'style-loader',
31+
'css-loader',
32+
'sprite-smith-loader'
33+
],
34+
},
35+
],
36+
},
37+
resolveLoader: {
38+
// tell webpack where to find modules
39+
modules: ['node_modules', path.join(__dirname, './loaders')],
40+
},
41+
plugins: [
42+
new webpack.HotModuleReplacementPlugin(),
43+
new HtmlWebpackPlugin({
44+
template: './resource/index.html',
45+
}),
46+
],
47+
devServer: {
48+
hot: true,
49+
contentBase: './dist',
50+
port: 4000,
51+
https: false,
52+
open: true
53+
},
54+
}

dist/index.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,6 @@ module.exports = function (source) {
125125

126126
}
127127
});
128-
console.log(bgszLineStart, bgszLineEnd, bgLineStart, bgLineEnd)
129128

130129
// 处理 background-size
131130
parsedValue.walk(node => {

0 commit comments

Comments
 (0)