mirror of
https://github.com/palxiao/poster-design.git
synced 2025-06-08 03:19:59 +08:00
style: background component move to right Panel
This commit is contained in:
parent
64a272ef12
commit
a2bf3de99a
@ -11,15 +11,15 @@
|
|||||||
|
|
||||||
[](https://design.palxp.cn/)
|
[](https://design.palxp.cn/)
|
||||||
|
|
||||||
- 丝滑的操作体验,丰富的交互细节,基础功能完善
|
- 丝滑的页面操作体验,丰富的交互细节,基础功能完善
|
||||||
- 采用服务端生成图片,确保多端出图统一性,支持各种 CSS 特性
|
- 采用服务端生成图片,能确保多端出图统一性,支持各种 CSS 特性
|
||||||
- 简易 AI 抠图工具,上传图片一键去除背景
|
- 简易 AI 抠图工具,上传图片一键去除背景
|
||||||
- 技术栈:Vue3 、Vite2 、Vuex 、ElementPlus
|
- 技术栈:Vue3 、Vite2 、Vuex 、ElementPlus,开发体验畅快
|
||||||
- 图片生成:Puppeteer、Express
|
- 图片生成:Puppeteer、Express
|
||||||
|
|
||||||
### 支持功能
|
### 支持功能
|
||||||
|
|
||||||
- 导入 PSD 文件解析成模板、在线导出图片下载
|
- 导入 PSD 文件解析成模板、在线导出图片下载。
|
||||||
- 元素拖拽、组合、缩放、层级调整、对齐等操作。
|
- 元素拖拽、组合、缩放、层级调整、对齐等操作。
|
||||||
- 图片素材插入、替换、裁剪,图片容器等功能。
|
- 图片素材插入、替换、裁剪,图片容器等功能。
|
||||||
- SVG 素材颜色、透明度编辑,文字花字组合。
|
- SVG 素材颜色、透明度编辑,文字花字组合。
|
||||||
|
@ -9,7 +9,7 @@ module.exports = {
|
|||||||
'ie >= 8',
|
'ie >= 8',
|
||||||
'last 10 versions', // 所有主流浏览器最近10版本用
|
'last 10 versions', // 所有主流浏览器最近10版本用
|
||||||
],
|
],
|
||||||
grid: true,
|
grid: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
* @Author: ShawnPhang
|
* @Author: ShawnPhang
|
||||||
* @Date: 2021-07-17 11:20:22
|
* @Date: 2021-07-17 11:20:22
|
||||||
* @Description:
|
* @Description:
|
||||||
* @LastEditors: rayadaschn 115447518+rayadaschn@users.noreply.github.com
|
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||||
* @LastEditTime: 2023-09-01 14:15:14
|
* @LastEditTime: 2024-01-24 17:07:44
|
||||||
*/
|
*/
|
||||||
export default [
|
export default [
|
||||||
{
|
{
|
||||||
@ -31,14 +31,14 @@ export default [
|
|||||||
show: false,
|
show: false,
|
||||||
component: 'photo-list-wrap',
|
component: 'photo-list-wrap',
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// name: '背景',
|
||||||
|
// icon: 'icon-beijing',
|
||||||
|
// show: false,
|
||||||
|
// component: 'bg-img-list-wrap',
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
name: '背景',
|
name: '工具箱',
|
||||||
icon: 'icon-beijing',
|
|
||||||
show: false,
|
|
||||||
component: 'bg-img-list-wrap',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '工具',
|
|
||||||
icon: 'icon-zujian01',
|
icon: 'icon-zujian01',
|
||||||
show: false,
|
show: false,
|
||||||
component: 'tools-list-wrap',
|
component: 'tools-list-wrap',
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<div class="widget-classify">
|
<div class="widget-classify">
|
||||||
<ul class="classify-wrap">
|
<ul class="classify-wrap">
|
||||||
<li v-for="(item, index) in widgetClassifyList" :key="index" :class="['classify-item', { 'active-classify-item': activeWidgetClassify === index }]" @click="clickClassify(index)">
|
<li v-for="(item, index) in widgetClassifyList" :key="index" :class="['classify-item', { 'active-classify-item': activeWidgetClassify === index }]" @click="clickClassify(index)">
|
||||||
<i :class="['iconfont', 'icon', item.icon]" :style="item.style"></i>
|
<div class="icon-box"><i :class="['iconfont', 'icon', item.icon]" :style="item.style" /></div>
|
||||||
<p>{{ item.name }}</p>
|
<p>{{ item.name }}</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -16,9 +16,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- <div v-show="active" class="side-wrap"><div class="pack__up" @click="active = false"><</div></div> -->
|
<!-- <div v-show="active" class="side-wrap"><div class="pack__up" @click="active = false"><</div></div> -->
|
||||||
<div v-show="active" class="side-wrap">
|
<div v-show="active" class="side-wrap">
|
||||||
<el-tooltip effect="dark" content="收起侧边栏" placement="right">
|
<!-- <el-tooltip effect="dark" content="收起侧边栏" placement="right"> -->
|
||||||
<div class="pack__up" @click="active = false"></div>
|
<div class="pack__up" @click="active = false"></div>
|
||||||
</el-tooltip>
|
<!-- </el-tooltip> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -49,7 +49,7 @@ export default {
|
|||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await nextTick()
|
await nextTick()
|
||||||
const { koutu } = route.query
|
const { koutu } = route.query
|
||||||
koutu && (state.activeWidgetClassify = 5)
|
koutu && (state.activeWidgetClassify = 4)
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
@ -125,9 +125,17 @@ export default {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
p {
|
p {
|
||||||
color: #9da3ac;
|
color: #666666;
|
||||||
|
font-weight: 600;
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
|
.icon-box {
|
||||||
|
width: 24px;
|
||||||
|
height: 27px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
.icon {
|
.icon {
|
||||||
color: #070707;
|
color: #070707;
|
||||||
}
|
}
|
||||||
|
@ -3,15 +3,15 @@
|
|||||||
* @Date: 2021-08-27 15:16:07
|
* @Date: 2021-08-27 15:16:07
|
||||||
* @Description: 背景图
|
* @Description: 背景图
|
||||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||||
* @LastEditTime: 2023-11-22 09:56:18
|
* @LastEditTime: 2024-01-24 16:39:27
|
||||||
-->
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="wrap">
|
<div class="wrap">
|
||||||
<div class="color__box">
|
<div class="color__box" :style="modelStyle.color">
|
||||||
<div v-for="c in colors" :key="c" :style="{ background: c }" class="color__item" @click="setBGcolor(c)"></div>
|
<div v-for="c in colors" :key="c" :style="{ background: c }" class="color__item" @click="setBGcolor(c)"></div>
|
||||||
</div>
|
</div>
|
||||||
<ul v-if="showList" v-infinite-scroll="loadData" class="infinite-list" :infinite-scroll-distance="150" style="overflow: auto">
|
<ul v-if="showList" v-infinite-scroll="loadData" class="infinite-list" :infinite-scroll-distance="150" style="overflow: auto">
|
||||||
<div class="list">
|
<div class="list" :style="modelStyle.list">
|
||||||
<imageTip v-for="(item, i) in bgList" :key="i + 'i'" :detail="item">
|
<imageTip v-for="(item, i) in bgList" :key="i + 'i'" :detail="item">
|
||||||
<el-image class="list__img" :src="item.thumb" fit="cover" lazy loading="lazy" @click.stop="selectItem(item)" @dragstart="dragStart($event, item)"></el-image>
|
<el-image class="list__img" :src="item.thumb" fit="cover" lazy loading="lazy" @click.stop="selectItem(item)" @dragstart="dragStart($event, item)"></el-image>
|
||||||
</imageTip>
|
</imageTip>
|
||||||
@ -23,11 +23,16 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, reactive, toRefs, watch } from 'vue'
|
import { defineComponent, reactive, toRefs, computed } from 'vue'
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import { mapActions, useStore } from 'vuex'
|
import { mapActions, useStore } from 'vuex'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
model: {
|
||||||
|
default: 'widgetPanel'
|
||||||
|
}
|
||||||
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
@ -37,6 +42,19 @@ export default defineComponent({
|
|||||||
showList: true,
|
showList: true,
|
||||||
colors: ['#000000ff', '#999999ff', '#CCCCCCff', '#FFFFFFff', '#E65353ff', '#FFD835ff', '#70BC59ff', '#607AF4ff', '#976BEEff'],
|
colors: ['#000000ff', '#999999ff', '#CCCCCCff', '#FFFFFFff', '#E65353ff', '#FFD835ff', '#70BC59ff', '#607AF4ff', '#976BEEff'],
|
||||||
})
|
})
|
||||||
|
// 临时用于改变样式
|
||||||
|
const models: any = {
|
||||||
|
widgetPanel: {
|
||||||
|
color: 'padding: 1.2rem 1rem',
|
||||||
|
list: 'grid-template-columns: auto auto auto;padding: 0 1rem;',
|
||||||
|
},
|
||||||
|
stylePanel: {
|
||||||
|
color: 'padding: 1.2rem 0;',
|
||||||
|
list: 'grid-template-columns: repeat(3, 76px);',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const modelStyle = computed(() => models[props.model])
|
||||||
|
|
||||||
const pageOptions = { page: 0, pageSize: 20 }
|
const pageOptions = { page: 0, pageSize: 20 }
|
||||||
|
|
||||||
const loadData = () => {
|
const loadData = () => {
|
||||||
@ -91,6 +109,7 @@ export default defineComponent({
|
|||||||
load,
|
load,
|
||||||
setBGcolor,
|
setBGcolor,
|
||||||
loadData,
|
loadData,
|
||||||
|
modelStyle
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -135,14 +154,13 @@ export default defineComponent({
|
|||||||
// }
|
// }
|
||||||
.list {
|
.list {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0 1rem;
|
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: auto auto auto;
|
grid-gap: 5px;
|
||||||
&__img {
|
&__img {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
width: 92px;
|
width: 100%;
|
||||||
height: 92px;
|
height: 92px;
|
||||||
margin-bottom: 5px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
&__img:hover::before {
|
&__img:hover::before {
|
||||||
content: ' ';
|
content: ' ';
|
||||||
@ -166,7 +184,6 @@ export default defineComponent({
|
|||||||
|
|
||||||
.color {
|
.color {
|
||||||
&__box {
|
&__box {
|
||||||
padding: 1.2rem 1rem;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="page-style">
|
<div id="page-style">
|
||||||
<el-collapse v-model="activeNames">
|
<div v-if="showBgLib" style="width: 256px;height: 100%;">
|
||||||
|
<span class="header-back" @click="showBgLib = false">
|
||||||
|
<i class="iconfont icon-right"></i> 选择背景
|
||||||
|
</span>
|
||||||
|
<bg-img-list-wrap style="padding-top: 2rem;" model="stylePanel" />
|
||||||
|
</div>
|
||||||
|
<el-collapse v-else v-model="activeNames">
|
||||||
<el-collapse-item title="画布尺寸" name="1">
|
<el-collapse-item title="画布尺寸" name="1">
|
||||||
<div class="position-size">
|
<div class="position-size">
|
||||||
<number-input v-model="innerElement.width" label="宽" :maxValue="5000" @finish="(value) => finish('width', value)" />
|
<number-input v-model="innerElement.width" label="宽" :maxValue="5000" @finish="(value) => finish('width', value)" />
|
||||||
@ -8,6 +14,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-collapse-item>
|
</el-collapse-item>
|
||||||
<el-collapse-item title="背景设置" name="2">
|
<el-collapse-item title="背景设置" name="2">
|
||||||
|
<el-button style="width: 100%; margin: 0 0 1rem 0;" type="primary" link @click="showBgLib = true">在背景库中选择</el-button>
|
||||||
<Tabs :value="mode" @update:value="onChangeMode">
|
<Tabs :value="mode" @update:value="onChangeMode">
|
||||||
<TabPanel v-for="label in modes" :key="label" :label="label"></TabPanel>
|
<TabPanel v-for="label in modes" :key="label" :label="label"></TabPanel>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
@ -15,16 +22,14 @@
|
|||||||
<!-- <bg-img-select :img="innerElement.backgroundImage"/> -->
|
<!-- <bg-img-select :img="innerElement.backgroundImage"/> -->
|
||||||
<div v-if="mode === '图片' && innerElement.backgroundImage" style="margin-top: 2rem">
|
<div v-if="mode === '图片' && innerElement.backgroundImage" style="margin-top: 2rem">
|
||||||
<el-image style="max-height: 428px" :src="innerElement.backgroundImage" fit="contain"></el-image>
|
<el-image style="max-height: 428px" :src="innerElement.backgroundImage" fit="contain"></el-image>
|
||||||
<el-button style="width: 100%; margin-top: 0.7rem" size="small" @click="deleteBg">删除</el-button>
|
<el-button class="btn-wrap" size="small" @click="deleteBg">删除</el-button>
|
||||||
</div>
|
</div>
|
||||||
<uploader v-show="mode === '图片'" style="width: 100%; margin-top: 0.7rem" @done="uploadImgDone">
|
<uploader v-show="mode === '图片'" class="btn-wrap" @done="uploadImgDone">
|
||||||
<el-button style="width: 100%" plain>{{ innerElement.backgroundImage ? '替换背景' : '上传背景' }}图</el-button>
|
<el-button style="width: 100%" plain>{{ innerElement.backgroundImage ? '更换背景' : '上传背景' }}图</el-button>
|
||||||
</uploader>
|
</uploader>
|
||||||
<el-button v-show="mode === '图片' && innerElement.backgroundImage" style="width: 100%; margin-top: 0.7rem" size="small" @click="downloadBG">{{ downP ? downP + ' %' : '下载背景图' }}</el-button>
|
<el-button v-show="mode === '图片' && innerElement.backgroundImage" class="btn-wrap" size="small" @click="downloadBG">{{ downP ? downP + ' %' : '下载背景图' }}</el-button>
|
||||||
|
|
||||||
</el-collapse-item>
|
</el-collapse-item>
|
||||||
<!-- <el-collapse-item title="其他设置" name="3">
|
|
||||||
<el-input v-model="innerElement.name" label="名称" @finish="(value) => finish('name', value)" />
|
|
||||||
</el-collapse-item> -->
|
|
||||||
</el-collapse>
|
</el-collapse>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -52,9 +57,9 @@ export default {
|
|||||||
tag: false,
|
tag: false,
|
||||||
ingoreKeys: ['backgroundColor', 'name', 'width', 'height'],
|
ingoreKeys: ['backgroundColor', 'name', 'width', 'height'],
|
||||||
downP: 0,
|
downP: 0,
|
||||||
// canvasRunning: false,
|
|
||||||
mode: '颜色',
|
mode: '颜色',
|
||||||
modes: ['颜色', '图片'],
|
modes: ['颜色', '图片'],
|
||||||
|
showBgLib: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -189,4 +194,25 @@ export default {
|
|||||||
.select {
|
.select {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
.btn-wrap {
|
||||||
|
width: 100%; margin-top: 0.7rem;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
&-back {
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: #333;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
height: 2.9rem;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
|
background: #ffffff;
|
||||||
|
width: 259px;
|
||||||
|
.icon-right {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user