Commit f90a9007 by haojie

1

parent 0a454796
......@@ -10,7 +10,9 @@
"dependencies": {
"dayjs": "^1.11.7",
"event-source-polyfill": "^1.0.31",
"html2canvas": "^1.4.1",
"js-cookie": "^3.0.1",
"swiper": "^9.2.3",
"tdesign-icons-vue-next": "^0.1.7",
"tdesign-vue-next": "^1.0.5",
"uuid": "^9.0.0",
......@@ -2617,6 +2619,14 @@
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"node_modules/base64-arraybuffer": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
"integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==",
"engines": {
"node": ">= 0.6.0"
}
},
"node_modules/body-parser": {
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
......@@ -3140,6 +3150,14 @@
"node": ">= 8"
}
},
"node_modules/css-line-break": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz",
"integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
"dependencies": {
"utrie": "^1.0.2"
}
},
"node_modules/css-select": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz",
......@@ -3835,6 +3853,18 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/html2canvas": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz",
"integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
"dependencies": {
"css-line-break": "^2.1.0",
"text-segmentation": "^1.0.3"
},
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/http-errors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
......@@ -5075,6 +5105,11 @@
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
"deprecated": "Please use @jridgewell/sourcemap-codec instead"
},
"node_modules/ssr-window": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/ssr-window/-/ssr-window-4.0.2.tgz",
"integrity": "sha512-ISv/Ch+ig7SOtw7G2+qkwfVASzazUnvlDTwypdLoPoySv+6MqlOV10VwPSE6EWkGjhW50lUmghPmpYZXMu/+AQ=="
},
"node_modules/stable": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz",
......@@ -5192,6 +5227,27 @@
"node": ">=10.13.0"
}
},
"node_modules/swiper": {
"version": "9.2.3",
"resolved": "https://registry.npmjs.org/swiper/-/swiper-9.2.3.tgz",
"integrity": "sha512-hxqcjIsYPP1fv+KIXPqGywl6ik8RBp0y0i9+TOIh55ca6SpZ5FrgNJ4QXPhsl6mlSBMEYPmh5zOKtZpI8zpWeQ==",
"funding": [
{
"type": "patreon",
"url": "https://www.patreon.com/swiperjs"
},
{
"type": "open_collective",
"url": "http://opencollective.com/swiper"
}
],
"dependencies": {
"ssr-window": "^4.0.2"
},
"engines": {
"node": ">= 4.7.0"
}
},
"node_modules/systemjs": {
"version": "6.14.1",
"resolved": "https://registry.npmjs.org/systemjs/-/systemjs-6.14.1.tgz",
......@@ -5256,6 +5312,14 @@
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true
},
"node_modules/text-segmentation": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz",
"integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
"dependencies": {
"utrie": "^1.0.2"
}
},
"node_modules/tiny-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
......@@ -5461,6 +5525,14 @@
"node": ">= 0.4.0"
}
},
"node_modules/utrie": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz",
"integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
"dependencies": {
"base64-arraybuffer": "^1.0.2"
}
},
"node_modules/uuid": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
......@@ -7549,6 +7621,11 @@
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"base64-arraybuffer": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
"integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ=="
},
"body-parser": {
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
......@@ -7932,6 +8009,14 @@
"which": "^2.0.1"
}
},
"css-line-break": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz",
"integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
"requires": {
"utrie": "^1.0.2"
}
},
"css-select": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz",
......@@ -8451,6 +8536,15 @@
"integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==",
"dev": true
},
"html2canvas": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz",
"integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
"requires": {
"css-line-break": "^2.1.0",
"text-segmentation": "^1.0.3"
}
},
"http-errors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
......@@ -9398,6 +9492,11 @@
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="
},
"ssr-window": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/ssr-window/-/ssr-window-4.0.2.tgz",
"integrity": "sha512-ISv/Ch+ig7SOtw7G2+qkwfVASzazUnvlDTwypdLoPoySv+6MqlOV10VwPSE6EWkGjhW50lUmghPmpYZXMu/+AQ=="
},
"stable": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz",
......@@ -9478,6 +9577,14 @@
"stable": "^0.1.8"
}
},
"swiper": {
"version": "9.2.3",
"resolved": "https://registry.npmjs.org/swiper/-/swiper-9.2.3.tgz",
"integrity": "sha512-hxqcjIsYPP1fv+KIXPqGywl6ik8RBp0y0i9+TOIh55ca6SpZ5FrgNJ4QXPhsl6mlSBMEYPmh5zOKtZpI8zpWeQ==",
"requires": {
"ssr-window": "^4.0.2"
}
},
"systemjs": {
"version": "6.14.1",
"resolved": "https://registry.npmjs.org/systemjs/-/systemjs-6.14.1.tgz",
......@@ -9532,6 +9639,14 @@
}
}
},
"text-segmentation": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz",
"integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
"requires": {
"utrie": "^1.0.2"
}
},
"tiny-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
......@@ -9674,6 +9789,14 @@
"integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
"dev": true
},
"utrie": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz",
"integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
"requires": {
"base64-arraybuffer": "^1.0.2"
}
},
"uuid": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
......
......@@ -14,7 +14,9 @@
"dependencies": {
"dayjs": "^1.11.7",
"event-source-polyfill": "^1.0.31",
"html2canvas": "^1.4.1",
"js-cookie": "^3.0.1",
"swiper": "^9.2.3",
"tdesign-icons-vue-next": "^0.1.7",
"tdesign-vue-next": "^1.0.5",
"uuid": "^9.0.0",
......
<svg width="24" height="42" viewBox="0 0 24 42" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M17.455 20.9368L0.807988 4.28972C0.672098 4.15366 0.564448 3.99208 0.491231 3.81427C0.418013 3.63646 0.380674 3.44592 0.381357 3.25363C0.38204 3.06134 0.420733 2.87107 0.495212 2.69379C0.569691 2.5165 0.678487 2.35569 0.81534 2.2206L1.85799 1.17795C2.13299 0.905028 2.50433 0.751263 2.89177 0.749887C3.27922 0.748511 3.65164 0.899635 3.92857 1.1706L22.6639 19.9059C22.7997 20.042 22.9072 20.2037 22.9803 20.3816C23.0534 20.5594 23.0906 20.75 23.0898 20.9423C23.0889 21.1346 23.0501 21.3248 22.9755 21.5021C22.9009 21.6793 22.792 21.84 22.655 21.975L3.92857 40.703C3.79249 40.8391 3.63082 40.9469 3.45287 41.0203C3.27492 41.0936 3.08422 41.131 2.89175 41.1303C2.69928 41.1296 2.50885 41.0909 2.33143 41.0163C2.154 40.9417 1.9931 40.8327 1.85799 40.6956L0.81534 39.653C0.542414 39.378 0.38865 39.0066 0.387274 38.6192C0.385898 38.2317 0.537022 37.8593 0.807988 37.5824L17.455 20.9353V20.9368Z" fill="#5D6067"/>
</svg>
\ No newline at end of file
<svg width="24" height="42" viewBox="0 0 24 42" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.54471 21.0632L23.1918 37.7103C23.3277 37.8463 23.4353 38.0079 23.5085 38.1857C23.5817 38.3635 23.6191 38.5541 23.6184 38.7464C23.6177 38.9387 23.579 39.1289 23.5045 39.3062C23.4301 39.4835 23.3213 39.6443 23.1844 39.7794L22.1418 40.822C21.8668 41.095 21.4954 41.2487 21.108 41.2501C20.7205 41.2515 20.3481 41.1004 20.0712 40.8294L1.33589 22.0941C1.2001 21.958 1.09256 21.7963 1.01947 21.6184C0.946377 21.4406 0.909172 21.25 0.909992 21.0577C0.910812 20.8654 0.94964 20.6752 1.02425 20.4979C1.09885 20.3207 1.20776 20.16 1.34471 20.025L20.0712 1.29705C20.2073 1.16093 20.3689 1.0531 20.5469 0.979748C20.7248 0.906399 20.9155 0.868992 21.108 0.869675C21.3005 0.870358 21.4909 0.909122 21.6683 0.983734C21.8458 1.05834 22.0067 1.16732 22.1418 1.3044L23.1844 2.34705C23.4573 2.62205 23.6111 2.99339 23.6125 3.38083C23.6139 3.76828 23.4627 4.1407 23.1918 4.41763L6.54471 21.0647V21.0632Z" fill="#5D6067"/>
</svg>
\ No newline at end of file
......@@ -58,6 +58,10 @@ const btns = [
label: 'AI视频',
path: '/AIVideo',
},
{
label: '图片处理',
path: '/ImgConversion',
},
// {
// label: '图片生成_自动化',
// path: '/',
......
.custom-home-swiper {
width: 100%;
display: flex;
align-items: center;
.swiper-wrapper {
height: 240px;
.swiper-slide {
display: flex;
justify-content: center;
.custom-silde-box {
width: 339px;
height: 100%;
.swiper_image {
height: 100%;
}
}
}
}
.prev-next {
cursor: pointer;
}
}
import { defineComponent } from 'vue';
import { defineComponent, onMounted, reactive, ref } from 'vue';
import './index.less';
import { Swiper, SwiperSlide } from 'swiper/vue';
import { Pagination, Navigation, Autoplay } from 'swiper';
import 'swiper/css';
import 'swiper/css/pagination';
export default defineComponent({
setup(props, ctx) {
return () => <div>111111111111</div>;
const imgs = {
prev: new URL(
'../../../../assets/svg/home/swiper_prev.svg',
import.meta.url
).href,
next: new URL(
'../../../../assets/svg/home/swiper_next.svg',
import.meta.url
).href,
};
const modules = ref([Navigation, Autoplay]);
const ScrollList = reactive({
list: [
{
img: new URL('../../../../assets/img/clothes.jpeg', import.meta.url)
.href,
},
{
img: new URL('../../../../assets/img/mote.jpeg', import.meta.url)
.href,
},
{
img: new URL('../../../../assets/img/clothes.jpeg', import.meta.url)
.href,
},
{
img: new URL('../../../../assets/img/mote.jpeg', import.meta.url)
.href,
},
{
img: new URL('../../../../assets/img/clothes.jpeg', import.meta.url)
.href,
},
{
img: new URL('../../../../assets/img/mote.jpeg', import.meta.url)
.href,
},
],
});
const goDetail = (item: any) => {
console.log(1);
};
return () => (
<div class="custom-home-swiper">
<div class="swiper-button-prev swiper-button-white prev-next">
<img src={imgs.prev} alt="" />
</div>
<Swiper
slidesPerView={4}
// spaceBetween: 30, //每个swiper-slide的间隔距离
preventClicksPropagation={true} //阻止click冒泡。拖动Swiper时阻止click事件
loop={true}
loopFillGroupWithBlank={true}
loopedSlides={2}
modules={modules.value}
navigation={{
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
}}
autoplay={{
delay: 2000,
stopOnLastSlide: false,
disableOnInteraction: true,
}}
>
{/* onClick={goDetail.bind(this, item)} */}
{ScrollList.list.map((item: any, index: number) => (
<SwiperSlide>
<div class="custom-silde-box">
<img src={item.img} class="swiper_image" />
</div>
</SwiperSlide>
))}
</Swiper>
<div class="swiper-button-next swiper-button-white prev-next">
<img src={imgs.next} alt="" />
</div>
</div>
);
},
});
<template>
<div class="">
<div class="custom-home-swiper">
<div class="swiper-button-prev swiper-button-white prev-next">
<img :src="imgs.prev" alt="" />
</div>
<Swiper
:slidesPerView="4"
:preventClicksPropagation="true"
:loop="true"
:loopFillGroupWithBlank="true"
:loopedSlides="2"
:modules="modules"
:navigation="{
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
}"
:autoplay="{
delay: 2000,
stopOnLastSlide: false,
disableOnInteraction: true,
}"
>
<!-- onClick={goDetail.bind(this, item)} -->
<SwiperSlide v-for="(item, index) in ScrollList.list" :key="index">
<div class="custom-silde-box">
<img :src="item.img" class="swiper_image" />
</div>
</SwiperSlide>
</Swiper>
<div class="swiper-button-next swiper-button-white prev-next">
<img :src="imgs.next" alt="" />
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { defineComponent, onMounted, reactive, ref } from 'vue';
import './index.less';
import { Swiper, SwiperSlide } from 'swiper/vue';
import { Pagination, Navigation, Autoplay } from 'swiper';
import 'swiper/css';
import 'swiper/css/pagination';
/**
* spaceBetween 每个swiper-slide的间隔距离
*/
const imgs = {
prev: new URL('../../../../assets/svg/home/swiper_prev.svg', import.meta.url)
.href,
next: new URL('../../../../assets/svg/home/swiper_next.svg', import.meta.url)
.href,
};
const modules = ref([Navigation, Autoplay]);
const ScrollList = reactive({
list: [
{
img: new URL('../../../../assets/img/clothes.jpeg', import.meta.url).href,
},
{
img: new URL('../../../../assets/img/mote.jpeg', import.meta.url).href,
},
{
img: new URL('../../../../assets/img/clothes.jpeg', import.meta.url).href,
},
{
img: new URL('../../../../assets/img/mote.jpeg', import.meta.url).href,
},
{
img: new URL('../../../../assets/img/clothes.jpeg', import.meta.url).href,
},
{
img: new URL('../../../../assets/img/mote.jpeg', import.meta.url).href,
},
],
});
const goDetail = (item: any) => {
console.log(1);
};
</script>
<style lang="less" scoped></style>
.swiper-box {
margin: 30px 0;
}
import { defineComponent } from 'vue';
import HomeSwiper from './components/HomeSwiper';
import HomeSwiper from './components/HomeSwiper/swiper.vue';
import './index.less';
export default defineComponent({
setup() {
return () => (
<div>
<div class="swiper-box">
<HomeSwiper></HomeSwiper>
</div>
</div>
);
},
});
<template>
<div
:class="[DefaultClassName, 'drag']"
:style="{
backgroundImage: `url(${img})`,
}"
></div>
</template>
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
const props = defineProps<{
id: string;
img: string;
}>();
// 默认类名
const DefaultClassName = ref('custom-drag-img' + props.id);
class Drag {
constructor(
target,
options = { limit: true, drag: true, zoom: true, minWidth: 0, minHeight: 0 }
) {
this.target = target;
this.options = options;
this.init();
}
// 初始化
init() {
this.target.style.position = 'relative';
this.getBoundary();
if (this.options.drag) {
this.drag();
}
if (this.options.zoom) {
this.addHorn();
this.addBorder();
this.leftZoom();
this.rightZoom();
this.topZoom();
this.bottomZoom();
this.leftTopZoom();
this.leftBottomZoom();
this.rightTopZoom();
this.rightBottomZoom();
}
}
// 获取父元素的宽高
getBoundary() {
this.maxWidth = this.target.parentNode.clientWidth;
this.maxHeight = this.target.parentNode.clientHeight;
}
// 获取自身起始信息
getInfo(e) {
this.width = this.target.clientWidth;
this.height = this.target.clientHeight;
let translateStr = this.target.style.transform;
if (translateStr) {
const reg = /\d+/g;
let translateArr = translateStr.match(reg);
this.tx = Number(translateArr[0]);
this.ty = Number(translateArr[1]);
} else {
this.tx = 0;
this.ty = 0;
}
this.startX = e.clientX;
this.startY = e.clientY;
}
// 拖动实现
drag() {
this.target.addEventListener('mousedown', (e) => {
this.getInfo(e);
document.onmousemove = (e) => {
if (this.options.limit) {
this.distanceX = Math.max(
0,
Math.min(
this.tx + e.clientX - this.startX,
this.maxWidth - this.width
)
);
this.distanceY = Math.max(
0,
Math.min(
this.ty + e.clientY - this.startY,
this.maxHeight - this.height
)
);
} else {
this.distanceX = this.tx + e.clientX - this.startX;
this.distanceY = this.ty + e.clientY - this.startY;
}
this.target.style.transform = `translate(${this.distanceX}px, ${this.distanceY}px)`;
};
document.onmouseup = () => {
document.onmousemove = null;
};
});
}
// 添加四个角
addHorn() {
this.leftTop = document.createElement('div');
this.rightTop = document.createElement('div');
this.leftBottom = document.createElement('div');
this.rightBottom = document.createElement('div');
this.leftTop.className = 'horn leftTop';
this.rightTop.className = 'horn rightTop';
this.leftBottom.className = 'horn leftBottom';
this.rightBottom.className = 'horn rightBottom';
this.target.append(this.leftTop);
this.target.append(this.rightTop);
this.target.append(this.leftBottom);
this.target.append(this.rightBottom);
}
// 添加四条边
addBorder() {
this.left = document.createElement('div');
this.right = document.createElement('div');
this._top = document.createElement('div');
this.bottom = document.createElement('div');
this.left.className = 'vertical left';
this.right.className = 'vertical right';
this._top.className = 'horizontal top';
this.bottom.className = 'horizontal bottom';
this.target.append(this.left);
this.target.append(this.right);
this.target.append(this._top);
this.target.append(this.bottom);
}
// 缩放实现
zoom(el, direction) {
el.addEventListener('mousedown', (e) => {
e.stopPropagation();
this.getInfo(e);
document.onmousemove = (e) => {
switch (direction) {
case 'left':
this.leftInfo(e);
break;
case 'right':
this.rightInfo(e);
break;
case 'top':
this.topInfo(e);
break;
case 'bottom':
this.bottomInfo(e);
break;
case 'leftTop':
this.leftTopInfo(e);
break;
case 'leftBottom':
this.leftBottomInfo(e);
break;
case 'rightTop':
this.rightTopInfo(e);
break;
case 'rightBottom':
this.rightBottomInfo(e);
break;
}
// 这里不能直接使用对this.newWidth隐式类型转换来判断,因为this.newWidth===0时,会使用this.width
let width = this.newWidth !== undefined ? this.newWidth : this.width;
let height =
this.newHeight !== undefined ? this.newHeight : this.height;
let translateX =
this.distanceX !== undefined ? this.distanceX : this.tx;
let translateY =
this.distanceY !== undefined ? this.distanceY : this.ty;
this.target.style.width = `${width}px`;
this.target.style.height = `${height}px`;
this.target.style.transform = `translate(${translateX}px, ${translateY}px)`;
};
document.onmouseup = () => {
document.onmousemove = null;
};
});
}
// 获取缩放时宽高、translate等参数的值
leftInfo(e) {
this.newWidth = this.width - (e.clientX - this.startX);
this.distanceX = this.tx + (e.clientX - this.startX);
if (this.options.limit) {
this.newWidth = Math.max(
this.options.minWidth,
Math.min(this.newWidth, this.width + this.tx)
);
this.distanceX = Math.max(
0,
Math.min(this.distanceX, this.width + this.tx - this.options.minWidth)
);
}
}
rightInfo(e) {
this.newWidth = this.width + (e.clientX - this.startX);
if (this.options.limit) {
this.newWidth = Math.max(
this.options.minWidth,
Math.min(this.newWidth, this.maxWidth - this.tx)
);
}
}
topInfo(e) {
this.newHeight = this.height - (e.clientY - this.startY);
this.distanceY = this.ty + (e.clientY - this.startY);
if (this.options.limit) {
this.newHeight = Math.max(
this.options.minHeight,
Math.min(this.newHeight, this.height + this.ty)
);
this.distanceY = Math.max(
0,
Math.min(this.distanceY, this.height + this.ty - this.options.minHeight)
);
}
}
bottomInfo(e) {
this.newHeight = this.height + (e.clientY - this.startY);
if (this.options.limit) {
this.newHeight = Math.max(
this.options.minHeight,
Math.min(this.newHeight, this.maxHeight - this.ty)
);
}
}
leftTopInfo(e) {
this.leftInfo(e);
this.topInfo(e);
}
leftBottomInfo(e) {
this.leftInfo(e);
this.bottomInfo(e);
}
rightTopInfo(e) {
this.rightInfo(e);
this.topInfo(e);
}
rightBottomInfo(e) {
this.rightInfo(e);
this.bottomInfo(e);
}
leftZoom() {
this.zoom(this.left, 'left');
}
rightZoom() {
this.zoom(this.right, 'right');
}
topZoom() {
this.zoom(this._top, 'top');
}
bottomZoom() {
this.zoom(this.bottom, 'bottom');
}
leftTopZoom() {
this.zoom(this.leftTop, 'leftTop');
}
leftBottomZoom() {
this.zoom(this.leftBottom, 'leftBottom');
}
rightTopZoom() {
this.zoom(this.rightTop, 'rightTop');
}
rightBottomZoom() {
this.zoom(this.rightBottom, 'rightBottom');
}
}
onMounted(() => {
let dragEl = document.querySelector(`.${DefaultClassName.value}`);
let t = new Drag(dragEl);
});
</script>
<style lang="less">
.drag {
height: 100px;
width: 100px;
background-repeat: no-repeat;
background-size: 100% 100%;
-moz-background-size: 100% 100%;
.horn {
width: 14px;
height: 14px;
/* background-color: red; */
position: absolute;
}
.vertical {
width: 10px;
height: calc(100% - 14px);
margin: 7px 0px;
position: absolute;
/* background-color: #000; */
cursor: col-resize;
}
.horizontal {
width: calc(100% - 14px);
height: 10px;
margin: 0px 7px;
position: absolute;
/* background-color: #000; */
cursor: row-resize;
}
.top {
top: -5px;
left: 0;
}
.left {
top: 0;
left: -5px;
}
.bottom {
left: 0;
bottom: -5px;
}
.right {
top: 0;
right: -5px;
}
.leftTop {
cursor: nw-resize;
left: -7px;
top: -7px;
}
.rightTop {
cursor: ne-resize;
right: -7px;
top: -7px;
}
.leftBottom {
cursor: sw-resize;
bottom: -7px;
left: -7px;
}
.rightBottom {
cursor: se-resize;
right: -7px;
bottom: -7px;
}
}
</style>
<template>
<div class="change-img">
<div>
<!-- <div style="color: white">宽高:</div>
<TInput v-model="input_value" style="width: 100px"></TInput> -->
<a id="link"></a>
<div class="course-container" id="myImage">
<template v-if="backimg">
<div class="course">
<img :src="backimg" />
</div>
</template>
<template v-else>
<div class="empty-background"></div>
</template>
<template v-if="MarkImg.list.length">
<div class="drag-img-parent">
<template v-for="(item, index) in MarkImg.list" :key="index">
<ImageDarg :id="item.id" :img="item.img"></ImageDarg>
</template>
</div>
</template>
<!-- <div
class="code"
:style="{ top: DragData.top + 'px', left: DragData.left + 'px' }"
>
<img
id="clothes_img"
:src="imgs.upImg"
:style="{
width: DragData.width + 'px',
height: DragData.height + 'px',
}"
/>
<template v-if="img_src">
<img :src="img_src" alt="" />
</template>
</div> -->
</div>
</div>
<div class="custom-tools">
<!-- 背景图 -->
<UploadImg
@SubmitImg="SubmitBackImg"
:list_len="MarkImg.list.length"
label="选择背景图"
></UploadImg>
<div class="custom-line"></div>
<div class="chose-other-img-box">
<UploadImg
@SubmitImg="SubmitImg"
:list_len="MarkImg.list.length"
label="选择其他图片"
></UploadImg>
<TButton @click="DeleteLast">删除最后一张子图</TButton>
</div>
<TButton class="save-button" @click="save()">保存</TButton>
</div>
</div>
</template>
<script setup lang="ts">
// 添加可以拖拽功能,放大缩小功能
import html2canvas from 'html2canvas';
import { onMounted, reactive, ref, watch } from 'vue';
import { Input as TInput, Button as TButton } from 'tdesign-vue-next';
import ImageDarg from './img_darg.vue';
import UploadImg from './upload.vue';
const imgs = {
backimg: new URL('../../../assets/img/mote2.png', import.meta.url).href,
// ../../../assets/img/yifu.png 无背景色的
upImg: new URL('../../../assets/img/clothes.jpeg', import.meta.url).href,
};
const backimg = ref('');
// 上传的列表
const MarkImg = reactive({
list: [],
});
// 上传的图片src
const img_src = ref('');
// 可拖拽图片默认的top,left
const default_top = 300;
const default_left = 300;
// 拖拽数据
const DragData = reactive({
start: null,
top: default_top,
old_top: default_top,
left: default_left,
old_left: default_left,
is_first: true,
// 判断图片要执行的动作类型--默认拖动
event_type: 'darg',
// 宽高
width: 150,
height: 150,
});
// 输入框的值
const input_value = ref(default_top);
watch(
() => input_value.value,
(v) => {
DragData.width = v;
DragData.height = v;
}
);
// 删除最后一个
const DeleteLast = () => {
if (MarkImg.list.length) {
MarkImg.list.pop();
}
};
// 背景图
const SubmitBackImg = (obj: any) => {
backimg.value = obj.img;
};
// 返回的图片base64
const SubmitImg = (obj: any) => {
MarkImg.list.push(obj);
};
const save = () => {
html2canvas(document.querySelector('#myImage')).then((canvas) => {
var image = canvas
.toDataURL('image/png')
.replace('image/png', 'image/octet-stream'); // here is the most important part because if you dont replace you will get a DOM 18 exception.
//save as download without name and extension
//window.location.href = image;
var link = document.getElementById('link');
link.setAttribute('download', 'my.png');
link.setAttribute(
'href',
canvas.toDataURL('image/png').replace('image/png', 'image/octet-stream')
);
link.click();
});
};
//
onMounted(() => {
// darg();
});
// 获取鼠标点击位于元素的哪个位置
const get_offset = (el: HTMLElement) => {
let client = el.getBoundingClientRect();
console.log(client);
};
// 拖拽
const darg = () => {
// 获取当前元素
let oDiv = document.querySelector('#clothes_img');
oDiv.onmousedown = (e) => {
// 算出鼠标相对元素的位置
let disX = e.clientX - oDiv.offsetLeft;
let disY = e.clientY - oDiv.offsetTop;
// 获取鼠标按下的位置
// get_offset(oDiv);
//
document.onmousemove = (e) => {
// 用鼠标的位置减去鼠标相对元素的位置,得到移动的距离
let left = e.clientX - disX;
let top = e.clientY - disY;
// 第一次拖拽使用这个
if (DragData.is_first) {
DragData.left = default_left + left;
DragData.top = default_top + top;
} else {
// 二次拖拽
DragData.left = DragData.old_left + left;
DragData.top = DragData.old_top + top;
}
};
document.onmouseup = () => {
DragData.is_first = false;
DragData.old_left = DragData.left;
DragData.old_top = DragData.top;
document.onmousemove = null;
document.onmouseup = null;
};
return false;
};
};
</script>
<style scoped lang="less">
.change-img {
display: flex;
.custom-tools {
position: relative;
flex: 1;
padding-left: 30px;
box-sizing: border-box;
.save-button {
position: absolute;
right: 0;
bottom: 0;
}
.custom-line {
height: 30px;
}
.chose-other-img-box {
display: flex;
& > :last-child {
margin-left: 12px;
}
}
}
}
.course-container {
height: 1024px;
// width: 724px;
width: 1024px;
position: relative;
}
.course {
z-index: 1;
position: absolute;
// width: 100%;
height: 100%;
img {
// width: 100%;
height: 100%;
}
}
.empty-background {
width: 100%;
height: 100%;
border: 1px dashed #00f9f9;
}
.code {
z-index: 2;
position: absolute;
width: 150px;
height: 150px;
img {
width: 100%;
height: 100%;
cursor: move;
}
}
.drag-img-parent {
width: 100%;
height: 100%;
position: relative;
z-index: 3;
}
</style>
<template>
<div class="fileUpload btn btn-primary">
<TButton
>{{ label }}
<input
class="custom-upload-file"
type="file"
@change="displayimg"
name="myfile"
accept="image/png, image/jpeg"
required
multiple
/>
</TButton>
</div>
</template>
<script lang="ts" setup>
import { Button as TButton } from 'tdesign-vue-next';
const props = defineProps<{
list_len: number;
label: string;
}>();
const emit = defineEmits(['SubmitImg']);
const displayimg = (e) => {
// //获取第一个文件对象
// var file = e.target.files[0];
// //判断当前是否支持使用FileReader
// if (window.FileReader) {
// //创建读取文件的对象
// var fr = new FileReader();
// //以读取文件字符串的方式读取文件 但是不能直接读取file
// //因为文件的内容是存在file对象下面的files数组中的
// //该方法结束后图片会以data:URL格式的字符串(base64编码)存储在fr对象的result中
// fr.readAsDataURL(file);
// fr.onloadend = function () {
// // 添加到列表
// emit('SubmitImg', {
// img: fr.result.replace(/\s/g, encodeURIComponent(' ')),
// id: props.list_len + 1 + '',
// });
// };
// }
// 循环获取
let files = e.target.files;
for (let i = 0, j = files.length; i < j; i++) {
console.log(files[i]);
//判断当前是否支持使用FileReader
if (window.FileReader) {
//创建读取文件的对象
var fr = new FileReader();
//以读取文件字符串的方式读取文件 但是不能直接读取file
//因为文件的内容是存在file对象下面的files数组中的
//该方法结束后图片会以data:URL格式的字符串(base64编码)存储在fr对象的result中
fr.readAsDataURL(files[i]);
fr.onloadend = function () {
// 添加到列表
emit('SubmitImg', {
img: fr.result.replace(/\s/g, encodeURIComponent(' ')),
id: props.list_len + 1 + '',
});
};
}
}
};
</script>
<style lang="less">
.fileUpload {
position: relative;
overflow: hidden;
height: 32px;
color: white;
font-size: 16px;
.custom-upload-file {
position: absolute;
top: 0;
right: 0;
margin: 0;
padding: 0;
cursor: pointer;
opacity: 0;
filter: alpha(opacity=0);
}
}
</style>
<template>
<div class="custom-img-conversion">
<ImageEdit></ImageEdit>
</div>
</template>
<script lang="ts" setup>
import ImageEdit from './components/img_edit.vue';
</script>
<style lang="less">
.custom-img-conversion {
margin-top: 30px;
}
</style>
<template>
<!-- <div class="custom-home-page-login">
<div class="custom-home-page-login">
<Login></Login>
</div> -->
<div>
<TestSwiper></TestSwiper>
</div>
<!-- <div>
<TestSwiper></TestSwiper>
</div> -->
</template>
<script lang="ts" setup>
import Login from "./components/login.vue";
import TestSwiper from "@/components/custom/swiper/test.vue";
import Login from './components/login.vue';
import TestSwiper from '@/components/custom/swiper/test.vue';
</script>
<style lang="less">
@import "@/style/variables.less";
@import "@/style/flex.less";
@import '@/style/variables.less';
@import '@/style/flex.less';
.custom-home-page-login {
background: #ffffff;
height: 100%;
......
......@@ -20,6 +20,15 @@ export default [
header: true,
},
},
// ImgConversion
{
path: '/ImgConversion',
name: 'ImgConversion',
component: () => import('@/pages/ImgConversion/index.vue'),
meta: {
header: true,
},
},
// {
// path: '/gpt',
// name: 'gpt',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment