fix: fix some bug

This commit is contained in:
xiaoxian521
2021-04-20 14:33:07 +08:00
parent 9737014c0c
commit 055296ab53
11 changed files with 500 additions and 404 deletions

View File

@@ -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>
</>
)
);
},
})
});

View File

@@ -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;

View File

@@ -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>
</>
)
}
})
);
},
});

View File

@@ -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;
},
},
}
};