avatar.vue 3.35 KB
<template>
    <span :class="classes">
        <img :src="src" v-if="src" @error="handleError">
        <Icon :type="icon" :custom="customIcon" v-else-if="icon || customIcon"></Icon>
        <span ref="children" :class="[prefixCls + '-string']" :style="childrenStyle" v-else><slot></slot></span>
    </span>
</template>
<script>
    import Icon from '../icon';
    import { oneOf } from '../../utils/assist';

    const prefixCls = 'ivu-avatar';

    export default {
        name: 'Avatar',
        components: { Icon },
        props: {
            shape: {
                validator (value) {
                    return oneOf(value, ['circle', 'square']);
                },
                default: 'circle'
            },
            size: {
                validator (value) {
                    return oneOf(value, ['small', 'large', 'default']);
                },
                default () {
                    return !this.$IVIEW || this.$IVIEW.size === '' ? 'default' : this.$IVIEW.size;
                }
            },
            src: {
                type: String
            },
            icon: {
                type: String
            },
            customIcon: {
                type: String,
                default: ''
            },
        },
        data () {
            return {
                prefixCls: prefixCls,
                scale: 1,
                childrenWidth: 0,
                isSlotShow: false
            };
        },
        computed: {
            classes () {
                return [
                    `${prefixCls}`,
                    `${prefixCls}-${this.shape}`,
                    `${prefixCls}-${this.size}`,
                    {
                        [`${prefixCls}-image`]: !!this.src,
                        [`${prefixCls}-icon`]: !!this.icon || !!this.customIcon
                    }
                ];
            },
            childrenStyle () {
                let style = {};
                if (this.isSlotShow) {
                    style = {
                        msTransform: `scale(${this.scale})`,
                        WebkitTransform: `scale(${this.scale})`,
                        transform: `scale(${this.scale})`,
                        position: 'absolute',
                        display: 'inline-block',
                        left: `calc(50% - ${Math.round(this.childrenWidth / 2)}px)`
                    };
                }
                return style;
            }
        },
        methods: {
            setScale () {
                this.isSlotShow = !this.src && !this.icon;
                if (this.$refs.children) {
                    // set children width again to make slot centered
                    this.childrenWidth = this.$refs.children.offsetWidth;
                    const avatarWidth = this.$el.getBoundingClientRect().width;
                    // add 4px gap for each side to get better performance
                    if (avatarWidth - 8 < this.childrenWidth) {
                        this.scale = (avatarWidth - 8) / this.childrenWidth;
                    } else {
                        this.scale = 1;
                    }
                }
            },
            handleError (e) {
                this.$emit('on-error', e);
            }
        },
        mounted () {
            this.setScale();
        },
        updated () {
            this.setScale();
        }
    };
</script>