uni-image-editor 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +98 -0
- package/components/edit-graffiti-config.vue +151 -0
- package/components/edit-text-config.vue +112 -0
- package/components/image-clipper/image-clipper.vue +1009 -0
- package/components/image-clipper/img/photo.svg +19 -0
- package/components/image-clipper/img/rotate.svg +15 -0
- package/components/image-clipper/index.scss +184 -0
- package/components/image-clipper/utils.js +280 -0
- package/components/input-text-modal.vue +431 -0
- package/image-editor.vue +971 -0
- package/js/const.js +242 -0
- package/js/editor.js +1179 -0
- package/js/utils.js +316 -0
- package/package.json +29 -0
package/README.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# uni-image-editor
|
|
2
|
+
|
|
3
|
+
UniApp Vue2 图片编辑插件,支持图片裁剪、涂鸦、添加文字等功能。
|
|
4
|
+
|
|
5
|
+
## 功能特性
|
|
6
|
+
|
|
7
|
+
- 图片裁剪
|
|
8
|
+
- 图片涂鸦(支持多种形状)
|
|
9
|
+
- 添加文字
|
|
10
|
+
- 撤销/重做操作
|
|
11
|
+
- 清除编辑内容
|
|
12
|
+
|
|
13
|
+
## 安装
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install uni-image-editor
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## 使用方法
|
|
20
|
+
|
|
21
|
+
### 在 UniApp 项目中引入
|
|
22
|
+
|
|
23
|
+
```vue
|
|
24
|
+
<template>
|
|
25
|
+
<view>
|
|
26
|
+
<image-editor
|
|
27
|
+
ref="imageEditor"
|
|
28
|
+
:imgUrl="imageUrl"
|
|
29
|
+
@success="handleSuccess"
|
|
30
|
+
@cancel="handleCancel"
|
|
31
|
+
/>
|
|
32
|
+
</view>
|
|
33
|
+
</template>
|
|
34
|
+
|
|
35
|
+
<script>
|
|
36
|
+
import imageEditor from 'uni-image-editor';
|
|
37
|
+
|
|
38
|
+
export default {
|
|
39
|
+
components: {
|
|
40
|
+
imageEditor
|
|
41
|
+
},
|
|
42
|
+
data() {
|
|
43
|
+
return {
|
|
44
|
+
imageUrl: 'https://example.com/image.jpg'
|
|
45
|
+
};
|
|
46
|
+
},
|
|
47
|
+
methods: {
|
|
48
|
+
handleSuccess(data) {
|
|
49
|
+
console.log('保存图片:', data);
|
|
50
|
+
},
|
|
51
|
+
handleCancel() {
|
|
52
|
+
console.log('取消编辑');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
</script>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## API
|
|
60
|
+
|
|
61
|
+
### Props
|
|
62
|
+
|
|
63
|
+
| 参数 | 类型 | 说明 | 默认值 |
|
|
64
|
+
| --- | --- | --- | --- |
|
|
65
|
+
| imgUrl | String | 图片地址 | - |
|
|
66
|
+
| toolConfigs | Array | 工具配置数组 | DEFAULT_TOOLS_CONFIGS |
|
|
67
|
+
| canvasId | String | 画布ID | "image-editor-canvas" |
|
|
68
|
+
| convertImgType | String | 图片转换类型 | CONVERT_IMG_NET_TO_LOCAL_TYPE.canvas |
|
|
69
|
+
| maxTransparencyRate | Number | 最大透明度比率 | 5 |
|
|
70
|
+
|
|
71
|
+
### Events
|
|
72
|
+
|
|
73
|
+
| 事件名 | 说明 | 回调参数 |
|
|
74
|
+
| --- | --- | --- |
|
|
75
|
+
| success | 保存图片时触发 | 图片数据对象 { imgData: { url, tempFilePath, width, height } } |
|
|
76
|
+
| cancel | 取消编辑时触发 | - |
|
|
77
|
+
|
|
78
|
+
### Methods
|
|
79
|
+
|
|
80
|
+
| 方法名 | 说明 | 参数 | 返回值 |
|
|
81
|
+
| --- | --- | --- | --- |
|
|
82
|
+
| getEditorInsatcne | 获取编辑器实例 | - | 编辑器实例 |
|
|
83
|
+
| confirm | 确认保存 | - | Promise |
|
|
84
|
+
| cancel | 取消编辑 | - | - |
|
|
85
|
+
| clear | 清除所有编辑 | - | - |
|
|
86
|
+
| repeal | 撤销操作 | - | - |
|
|
87
|
+
| redo | 重做操作 | - | - |
|
|
88
|
+
|
|
89
|
+
## 注意事项
|
|
90
|
+
|
|
91
|
+
- 仅支持 UniApp Vue2 项目
|
|
92
|
+
- 依赖 UniApp 原生 API 进行图片处理
|
|
93
|
+
- 使用时需要传入有效的 imgUrl
|
|
94
|
+
- 在 H5 环境下,网络图片会被转换为 base64 格式
|
|
95
|
+
|
|
96
|
+
## 许可证
|
|
97
|
+
|
|
98
|
+
MIT
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
* @Author: msc 862078729@qq.com
|
|
3
|
+
* @Date: 2024-04-28 15:20:12
|
|
4
|
+
* @LastEditors: msc 862078729@qq.com
|
|
5
|
+
* @LastEditTime: 2024-05-06 16:48:35
|
|
6
|
+
* @FilePath: \code\components\image-editor\components\edit-graffiti-config.vue
|
|
7
|
+
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
|
8
|
+
-->
|
|
9
|
+
<template>
|
|
10
|
+
<view class="edit-graffiti-config">
|
|
11
|
+
<view class="shape-pick config-pick flex-align-center">
|
|
12
|
+
<text class="shape-pick-text">形状:</text>
|
|
13
|
+
<view class="shape-pick-list flex-align-center">
|
|
14
|
+
<view
|
|
15
|
+
v-for="(item, index) in configs.shapes"
|
|
16
|
+
class="shape-pick-item"
|
|
17
|
+
:key="index"
|
|
18
|
+
@tap="pickShape(item.name)"
|
|
19
|
+
>
|
|
20
|
+
<i
|
|
21
|
+
:class="`iconfont ${item.icon}`"
|
|
22
|
+
:style="{
|
|
23
|
+
color: shape === item.name ? '#2979ff' : '#000000',
|
|
24
|
+
}"
|
|
25
|
+
/>
|
|
26
|
+
</view>
|
|
27
|
+
</view>
|
|
28
|
+
</view>
|
|
29
|
+
<view class="color-pick config-pick flex-align-center">
|
|
30
|
+
<text class="color-pick-text">颜色:</text>
|
|
31
|
+
<view class="color-pick-list flex-align-center">
|
|
32
|
+
<view
|
|
33
|
+
v-for="item in configs.colors"
|
|
34
|
+
:key="item"
|
|
35
|
+
class="color-pick-item"
|
|
36
|
+
:class="{ 'active-color': color === item }"
|
|
37
|
+
:style="{ backgroundColor: item }"
|
|
38
|
+
@tap="pickColor(item)"
|
|
39
|
+
></view>
|
|
40
|
+
</view>
|
|
41
|
+
</view>
|
|
42
|
+
|
|
43
|
+
<view class="rough-pick config-pick flex-align-center">
|
|
44
|
+
<text class="rough-pick-text">粗细:</text>
|
|
45
|
+
<view class="rough-pick-list flex-align-center">
|
|
46
|
+
<view
|
|
47
|
+
v-for="(item, index) in configs.roughs"
|
|
48
|
+
:key="index"
|
|
49
|
+
class="rough-pick-item"
|
|
50
|
+
@tap="pickRough(item)"
|
|
51
|
+
:style="{
|
|
52
|
+
backgroundColor: rough === item ? '#2979ff' : 'gray',
|
|
53
|
+
height: item + 'px',
|
|
54
|
+
}"
|
|
55
|
+
></view>
|
|
56
|
+
</view>
|
|
57
|
+
</view>
|
|
58
|
+
</view>
|
|
59
|
+
</template>
|
|
60
|
+
|
|
61
|
+
<script>
|
|
62
|
+
export default {
|
|
63
|
+
name: "EditGraffitiConfig",
|
|
64
|
+
props: {
|
|
65
|
+
configs: {
|
|
66
|
+
type: Object,
|
|
67
|
+
default: () => ({}),
|
|
68
|
+
},
|
|
69
|
+
color: {
|
|
70
|
+
type: String,
|
|
71
|
+
default: () => "",
|
|
72
|
+
},
|
|
73
|
+
shape: {
|
|
74
|
+
type: String,
|
|
75
|
+
default: () => "",
|
|
76
|
+
},
|
|
77
|
+
rough: {
|
|
78
|
+
type: [Number, String],
|
|
79
|
+
default: () => "",
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
data() {
|
|
83
|
+
return {
|
|
84
|
+
// 涂鸦配置
|
|
85
|
+
graffitiConfig: {
|
|
86
|
+
color: "#000000", // 画笔颜色
|
|
87
|
+
size: 5, // 画笔大小
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
},
|
|
91
|
+
methods: {
|
|
92
|
+
pickShape(shape) {
|
|
93
|
+
this.$emit("update:shape", shape);
|
|
94
|
+
},
|
|
95
|
+
pickColor(color) {
|
|
96
|
+
this.$emit("update:color", color);
|
|
97
|
+
},
|
|
98
|
+
pickRough(rough) {
|
|
99
|
+
this.$emit("update:rough", rough);
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
</script>
|
|
104
|
+
|
|
105
|
+
<style scope lang="scss">
|
|
106
|
+
.edit-graffiti-config {
|
|
107
|
+
.flex-align-center {
|
|
108
|
+
display: flex;
|
|
109
|
+
align-items: center;
|
|
110
|
+
}
|
|
111
|
+
.config-pick {
|
|
112
|
+
margin: 20rpx 0;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.color-pick {
|
|
116
|
+
.color-pick-list {
|
|
117
|
+
}
|
|
118
|
+
.color-pick-item {
|
|
119
|
+
width: 30rpx;
|
|
120
|
+
height: 30rpx;
|
|
121
|
+
border-radius: 50%;
|
|
122
|
+
box-sizing: content-box;
|
|
123
|
+
margin-left: 39rpx;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
.shape-pick {
|
|
127
|
+
color: #000000;
|
|
128
|
+
.shape-pick-list {
|
|
129
|
+
}
|
|
130
|
+
.shape-pick-item {
|
|
131
|
+
font-size: 36rpx;
|
|
132
|
+
margin-left: 34rpx;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.active-color {
|
|
137
|
+
transform: scale(1.5);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.rough-pick {
|
|
141
|
+
.rough-pick-list {
|
|
142
|
+
}
|
|
143
|
+
.rough-pick-item {
|
|
144
|
+
width: 44rpx;
|
|
145
|
+
background-color: gray;
|
|
146
|
+
margin-left: 28rpx;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
</style>
|
|
151
|
+
·
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
* @Author: msc 862078729@qq.com
|
|
3
|
+
* @Date: 2024-04-28 15:20:12
|
|
4
|
+
* @LastEditors: msc 862078729@qq.com
|
|
5
|
+
* @LastEditTime: 2024-05-06 16:49:20
|
|
6
|
+
* @FilePath: \code\components\image-editor\components\text-config.vue
|
|
7
|
+
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
|
8
|
+
-->
|
|
9
|
+
<template>
|
|
10
|
+
<view class="text-config">
|
|
11
|
+
<view class="color-pick config-pick flex-align-center">
|
|
12
|
+
<text class="color-pick-text">颜色:</text>
|
|
13
|
+
<view class="color-pick-list flex-align-center">
|
|
14
|
+
<view
|
|
15
|
+
v-for="item in configs.colors"
|
|
16
|
+
:key="item"
|
|
17
|
+
class="color-pick-item"
|
|
18
|
+
:class="{ 'active-color': color === item }"
|
|
19
|
+
:style="{ backgroundColor: item }"
|
|
20
|
+
@tap="pickColor(item)"
|
|
21
|
+
></view>
|
|
22
|
+
</view>
|
|
23
|
+
</view>
|
|
24
|
+
|
|
25
|
+
<view class="size-pick config-pick flex-align-center">
|
|
26
|
+
<text class="size-pick-text">字号:</text>
|
|
27
|
+
<view class="size-pick-list flex-align-center">
|
|
28
|
+
<view
|
|
29
|
+
v-for="(item, index) in configs.sizes"
|
|
30
|
+
:key="index"
|
|
31
|
+
class="size-pick-item"
|
|
32
|
+
@tap="pickSize(item)"
|
|
33
|
+
:class="{ 'active-size': item === size }"
|
|
34
|
+
>{{ item }}</view
|
|
35
|
+
>
|
|
36
|
+
</view>
|
|
37
|
+
</view>
|
|
38
|
+
</view>
|
|
39
|
+
</template>
|
|
40
|
+
|
|
41
|
+
<script>
|
|
42
|
+
export default {
|
|
43
|
+
name: "EditTextConfig",
|
|
44
|
+
props: {
|
|
45
|
+
configs: {
|
|
46
|
+
type: Object,
|
|
47
|
+
default: () => ({}),
|
|
48
|
+
},
|
|
49
|
+
color: {
|
|
50
|
+
type: String,
|
|
51
|
+
default: () => "",
|
|
52
|
+
},
|
|
53
|
+
size: {
|
|
54
|
+
type: [Number, String],
|
|
55
|
+
default: () => "",
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
data() {
|
|
59
|
+
return {
|
|
60
|
+
// 涂鸦配置
|
|
61
|
+
};
|
|
62
|
+
},
|
|
63
|
+
methods: {
|
|
64
|
+
pickSize(size) {
|
|
65
|
+
this.$emit("update:size", size);
|
|
66
|
+
},
|
|
67
|
+
pickColor(color) {
|
|
68
|
+
this.$emit("update:color", color);
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
</script>
|
|
73
|
+
|
|
74
|
+
<style scope lang="scss">
|
|
75
|
+
.text-config {
|
|
76
|
+
.flex-align-center {
|
|
77
|
+
display: flex;
|
|
78
|
+
align-items: center;
|
|
79
|
+
}
|
|
80
|
+
.config-pick {
|
|
81
|
+
margin: 20rpx 0;
|
|
82
|
+
}
|
|
83
|
+
.color-pick {
|
|
84
|
+
.color-pick-list {
|
|
85
|
+
}
|
|
86
|
+
.color-pick-item {
|
|
87
|
+
width: 30rpx;
|
|
88
|
+
height: 30rpx;
|
|
89
|
+
border-radius: 50%;
|
|
90
|
+
box-sizing: content-box;
|
|
91
|
+
margin-left: 39rpx;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.active-color {
|
|
96
|
+
transform: scale(1.5);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.active-size {
|
|
100
|
+
font-weight: 700;
|
|
101
|
+
color: #2979ff;
|
|
102
|
+
}
|
|
103
|
+
.size-pick {
|
|
104
|
+
.size-pick-list {
|
|
105
|
+
font-size: 24rpx;
|
|
106
|
+
}
|
|
107
|
+
.size-pick-item {
|
|
108
|
+
margin-left: 42rpx;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
</style>
|