mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2026-01-20 16:53:37 +08:00
fix: fix some bug
This commit is contained in:
@@ -1,14 +1,22 @@
|
||||
import type { CSSProperties } from 'vue'
|
||||
import type { CSSProperties } from "vue";
|
||||
|
||||
import { defineComponent, onBeforeMount, nextTick, ref, unref, computed, PropType } from 'vue'
|
||||
import { templateRef } from '@vueuse/core'
|
||||
import { useAttrs } from '/@/utils/useAttrs'
|
||||
import { emitter } from '/@/utils/mitt'
|
||||
import {
|
||||
defineComponent,
|
||||
onBeforeMount,
|
||||
nextTick,
|
||||
ref,
|
||||
unref,
|
||||
computed,
|
||||
PropType,
|
||||
} from "vue";
|
||||
import { templateRef } from "@vueuse/core";
|
||||
import { useAttrs } from "/@/utils/useAttrs";
|
||||
import { emitter } from "/@/utils/mitt";
|
||||
|
||||
import Cropper from 'cropperjs'
|
||||
import 'cropperjs/dist/cropper.css'
|
||||
import Cropper from "cropperjs";
|
||||
import "cropperjs/dist/cropper.css";
|
||||
|
||||
type Options = Cropper.Options
|
||||
type Options = Cropper.Options;
|
||||
|
||||
const defaultOptions: Cropper.Options = {
|
||||
aspectRatio: 16 / 9,
|
||||
@@ -31,7 +39,7 @@ const defaultOptions: Cropper.Options = {
|
||||
guides: true,
|
||||
movable: true,
|
||||
rotatable: true,
|
||||
}
|
||||
};
|
||||
export default defineComponent({
|
||||
name: "Cropper",
|
||||
props: {
|
||||
@@ -44,11 +52,11 @@ export default defineComponent({
|
||||
},
|
||||
width: {
|
||||
type: [String, Number],
|
||||
default: '',
|
||||
default: "",
|
||||
},
|
||||
height: {
|
||||
type: [String, Number],
|
||||
default: '360px',
|
||||
default: "360px",
|
||||
},
|
||||
crossorigin: {
|
||||
type: String || Object,
|
||||
@@ -61,57 +69,63 @@ export default defineComponent({
|
||||
options: {
|
||||
type: Object as PropType<Options>,
|
||||
default: {},
|
||||
}
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const cropper: any = ref<Nullable<Cropper>>(null)
|
||||
const imgElRef = templateRef<HTMLElement | null>('imgElRef', null)
|
||||
const cropper: any = ref<Nullable<Cropper>>(null);
|
||||
const imgElRef = templateRef<HTMLElement | null>("imgElRef", null);
|
||||
|
||||
const isReady = ref(false)
|
||||
const isReady = ref(false);
|
||||
|
||||
const getImageStyle = computed(
|
||||
(): CSSProperties => {
|
||||
return {
|
||||
height: props.height,
|
||||
width: props.width,
|
||||
maxWidth: '100%',
|
||||
maxWidth: "100%",
|
||||
...props.imageStyle,
|
||||
}
|
||||
};
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
const getWrapperStyle = computed(
|
||||
(): CSSProperties => {
|
||||
const { height, width } = props
|
||||
return { width: `${width}`.replace(/px/, '') + 'px', height: `${height}`.replace(/px/, '') + 'px' }
|
||||
const { height, width } = props;
|
||||
return {
|
||||
width: `${width}`.replace(/px/, "") + "px",
|
||||
height: `${height}`.replace(/px/, "") + "px",
|
||||
};
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
async function init() {
|
||||
const imgEl = unref(imgElRef)
|
||||
const imgEl = unref(imgElRef);
|
||||
if (!imgEl) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
cropper.value = new Cropper(imgEl, {
|
||||
...defaultOptions,
|
||||
ready: () => {
|
||||
isReady.value = true
|
||||
isReady.value = true;
|
||||
},
|
||||
...props.options,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
onBeforeMount(() => {
|
||||
nextTick(() => {
|
||||
init()
|
||||
init();
|
||||
// tsx语法返回渲染模板,外部组件想调用内部方法或者获取setup里面的实例,暂时想到的办法是通过公共事件
|
||||
emitter.emit("cropperInstance", unref(cropper))
|
||||
})
|
||||
})
|
||||
emitter.emit("cropperInstance", unref(cropper));
|
||||
});
|
||||
});
|
||||
|
||||
return () => (
|
||||
<>
|
||||
<div class={useAttrs({ excludeListeners: true, excludeKeys: ['class'] })} style={unref(getWrapperStyle)}>
|
||||
<div
|
||||
class={useAttrs({ excludeListeners: true, excludeKeys: ["class"] })}
|
||||
style={unref(getWrapperStyle)}
|
||||
>
|
||||
<img
|
||||
ref="imgElRef"
|
||||
src={props.src}
|
||||
@@ -121,6 +135,6 @@ export default defineComponent({
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
);
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { App } from "vue"
|
||||
import countTo from "./src/CountTo"
|
||||
import { App } from "vue";
|
||||
import countTo from "./src/CountTo";
|
||||
|
||||
export const CountTo = Object.assign(countTo, {
|
||||
install(app: App) {
|
||||
app.component(countTo.name, countTo)
|
||||
}
|
||||
})
|
||||
app.component(countTo.name, countTo);
|
||||
},
|
||||
});
|
||||
|
||||
export default CountTo
|
||||
export default CountTo;
|
||||
|
||||
@@ -5,10 +5,9 @@ import {
|
||||
watch,
|
||||
onMounted,
|
||||
unref,
|
||||
toRef
|
||||
} from "vue"
|
||||
import { countToProps } from "./props"
|
||||
import { isNumber } from "/@/utils/is"
|
||||
} from "vue";
|
||||
import { countToProps } from "./props";
|
||||
import { isNumber } from "/@/utils/is";
|
||||
|
||||
export default defineComponent({
|
||||
name: "CountTo",
|
||||
@@ -16,17 +15,17 @@ export default defineComponent({
|
||||
emits: ["mounted", "callback"],
|
||||
setup(props, { emit }) {
|
||||
const state = reactive<{
|
||||
localStartVal: number
|
||||
printVal: number | null
|
||||
displayValue: string
|
||||
paused: boolean
|
||||
localDuration: number | null
|
||||
startTime: number | null
|
||||
timestamp: number | null
|
||||
rAF: any
|
||||
remaining: number | null
|
||||
color: string
|
||||
fontSize: string
|
||||
localStartVal: number;
|
||||
printVal: number | null;
|
||||
displayValue: string;
|
||||
paused: boolean;
|
||||
localDuration: number | null;
|
||||
startTime: number | null;
|
||||
timestamp: number | null;
|
||||
rAF: any;
|
||||
remaining: number | null;
|
||||
color: string;
|
||||
fontSize: string;
|
||||
}>({
|
||||
localStartVal: props.startVal,
|
||||
displayValue: formatNumber(props.startVal),
|
||||
@@ -38,63 +37,63 @@ export default defineComponent({
|
||||
remaining: null,
|
||||
rAF: null,
|
||||
color: null,
|
||||
fontSize: "16px"
|
||||
})
|
||||
fontSize: "16px",
|
||||
});
|
||||
|
||||
const getCountDown = computed(() => {
|
||||
return props.startVal > props.endVal
|
||||
})
|
||||
return props.startVal > props.endVal;
|
||||
});
|
||||
|
||||
watch([() => props.startVal, () => props.endVal], () => {
|
||||
if (props.autoplay) {
|
||||
start()
|
||||
start();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
function start() {
|
||||
const { startVal, duration, color, fontSize } = props
|
||||
state.localStartVal = startVal
|
||||
state.startTime = null
|
||||
state.localDuration = duration
|
||||
state.paused = false
|
||||
state.color = color
|
||||
state.fontSize = fontSize
|
||||
state.rAF = requestAnimationFrame(count)
|
||||
const { startVal, duration, color, fontSize } = props;
|
||||
state.localStartVal = startVal;
|
||||
state.startTime = null;
|
||||
state.localDuration = duration;
|
||||
state.paused = false;
|
||||
state.color = color;
|
||||
state.fontSize = fontSize;
|
||||
state.rAF = requestAnimationFrame(count);
|
||||
}
|
||||
|
||||
function pauseResume() {
|
||||
if (state.paused) {
|
||||
resume()
|
||||
state.paused = false
|
||||
resume();
|
||||
state.paused = false;
|
||||
} else {
|
||||
pause()
|
||||
state.paused = true
|
||||
pause();
|
||||
state.paused = true;
|
||||
}
|
||||
}
|
||||
|
||||
function pause() {
|
||||
cancelAnimationFrame(state.rAF)
|
||||
cancelAnimationFrame(state.rAF);
|
||||
}
|
||||
|
||||
function resume() {
|
||||
state.startTime = null
|
||||
state.localDuration = +(state.remaining as number)
|
||||
state.localStartVal = +(state.printVal as number)
|
||||
requestAnimationFrame(count)
|
||||
state.startTime = null;
|
||||
state.localDuration = +(state.remaining as number);
|
||||
state.localStartVal = +(state.printVal as number);
|
||||
requestAnimationFrame(count);
|
||||
}
|
||||
|
||||
function reset() {
|
||||
state.startTime = null
|
||||
cancelAnimationFrame(state.rAF)
|
||||
state.displayValue = formatNumber(props.startVal)
|
||||
state.startTime = null;
|
||||
cancelAnimationFrame(state.rAF);
|
||||
state.displayValue = formatNumber(props.startVal);
|
||||
}
|
||||
|
||||
function count(timestamp: number) {
|
||||
const { useEasing, easingFn, endVal } = props
|
||||
if (!state.startTime) state.startTime = timestamp
|
||||
state.timestamp = timestamp
|
||||
const progress = timestamp - state.startTime
|
||||
state.remaining = (state.localDuration as number) - progress
|
||||
const { useEasing, easingFn, endVal } = props;
|
||||
if (!state.startTime) state.startTime = timestamp;
|
||||
state.timestamp = timestamp;
|
||||
const progress = timestamp - state.startTime;
|
||||
state.remaining = (state.localDuration as number) - progress;
|
||||
if (useEasing) {
|
||||
if (unref(getCountDown)) {
|
||||
state.printVal =
|
||||
@@ -104,70 +103,75 @@ export default defineComponent({
|
||||
0,
|
||||
state.localStartVal - endVal,
|
||||
state.localDuration as number
|
||||
)
|
||||
);
|
||||
} else {
|
||||
state.printVal = easingFn(
|
||||
progress,
|
||||
state.localStartVal,
|
||||
endVal - state.localStartVal,
|
||||
state.localDuration as number
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (unref(getCountDown)) {
|
||||
state.printVal =
|
||||
state.localStartVal -
|
||||
(state.localStartVal - endVal) *
|
||||
(progress / (state.localDuration as number))
|
||||
(progress / (state.localDuration as number));
|
||||
} else {
|
||||
state.printVal =
|
||||
state.localStartVal +
|
||||
(endVal - state.localStartVal) *
|
||||
(progress / (state.localDuration as number))
|
||||
(progress / (state.localDuration as number));
|
||||
}
|
||||
}
|
||||
if (unref(getCountDown)) {
|
||||
state.printVal = state.printVal < endVal ? endVal : state.printVal
|
||||
state.printVal = state.printVal < endVal ? endVal : state.printVal;
|
||||
} else {
|
||||
state.printVal = state.printVal > endVal ? endVal : state.printVal
|
||||
state.printVal = state.printVal > endVal ? endVal : state.printVal;
|
||||
}
|
||||
state.displayValue = formatNumber(state.printVal)
|
||||
state.displayValue = formatNumber(state.printVal);
|
||||
if (progress < (state.localDuration as number)) {
|
||||
state.rAF = requestAnimationFrame(count)
|
||||
state.rAF = requestAnimationFrame(count);
|
||||
} else {
|
||||
emit("callback")
|
||||
emit("callback");
|
||||
}
|
||||
}
|
||||
|
||||
function formatNumber(num: number | string) {
|
||||
const { decimals, decimal, separator, suffix, prefix } = props
|
||||
num = Number(num).toFixed(decimals)
|
||||
num += ""
|
||||
const x = num.split(".")
|
||||
let x1 = x[0]
|
||||
const x2 = x.length > 1 ? decimal + x[1] : ""
|
||||
const rgx = /(\d+)(\d{3})/
|
||||
const { decimals, decimal, separator, suffix, prefix } = props;
|
||||
num = Number(num).toFixed(decimals);
|
||||
num += "";
|
||||
const x = num.split(".");
|
||||
let x1 = x[0];
|
||||
const x2 = x.length > 1 ? decimal + x[1] : "";
|
||||
const rgx = /(\d+)(\d{3})/;
|
||||
if (separator && !isNumber(separator)) {
|
||||
while (rgx.test(x1)) {
|
||||
x1 = x1.replace(rgx, "$1" + separator + "$2")
|
||||
x1 = x1.replace(rgx, "$1" + separator + "$2");
|
||||
}
|
||||
}
|
||||
return prefix + x1 + x2 + suffix
|
||||
return prefix + x1 + x2 + suffix;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (props.autoplay) {
|
||||
start()
|
||||
start();
|
||||
}
|
||||
emit("mounted")
|
||||
})
|
||||
emit("mounted");
|
||||
});
|
||||
|
||||
return () => (
|
||||
<>
|
||||
<span style={{
|
||||
color: props.color, fontSize: props.fontSize
|
||||
}}>{state.displayValue}</span>
|
||||
<span
|
||||
style={{
|
||||
color: props.color,
|
||||
fontSize: props.fontSize,
|
||||
}}
|
||||
>
|
||||
{state.displayValue}
|
||||
</span>
|
||||
</>
|
||||
)
|
||||
}
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { PropType } from 'vue'
|
||||
import { propTypes } from '/@/utils/propTypes'
|
||||
import { PropType } from "vue";
|
||||
import { propTypes } from "/@/utils/propTypes";
|
||||
export const countToProps = {
|
||||
startVal: propTypes.number.def(0),
|
||||
endVal: propTypes.number.def(2020),
|
||||
@@ -10,20 +10,22 @@ export const countToProps = {
|
||||
required: false,
|
||||
default: 0,
|
||||
validator(value: number) {
|
||||
return value >= 0
|
||||
return value >= 0;
|
||||
},
|
||||
},
|
||||
color: propTypes.string.def(),
|
||||
fontSize: propTypes.string.def(),
|
||||
decimal: propTypes.string.def('.'),
|
||||
separator: propTypes.string.def(','),
|
||||
prefix: propTypes.string.def(''),
|
||||
suffix: propTypes.string.def(''),
|
||||
decimal: propTypes.string.def("."),
|
||||
separator: propTypes.string.def(","),
|
||||
prefix: propTypes.string.def(""),
|
||||
suffix: propTypes.string.def(""),
|
||||
useEasing: propTypes.bool.def(true),
|
||||
easingFn: {
|
||||
type: Function as PropType<(t: number, b: number, c: number, d: number) => number>,
|
||||
type: Function as PropType<
|
||||
(t: number, b: number, c: number, d: number) => number
|
||||
>,
|
||||
default(t: number, b: number, c: number, d: number) {
|
||||
return (c * (-Math.pow(2, (-10 * t) / d) + 1) * 1024) / 1023 + b
|
||||
return (c * (-Math.pow(2, (-10 * t) / d) + 1) * 1024) / 1023 + b;
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user