个人说说vue组件

模仿B站评论样式

vue.js支持表情输入

个人说说vue组件

好看的评论组件 - undrawui组件库

在这里插入图片描述

Talk.vue

<template>
    <div style="width: 632px;box-sizing: border-box;margin: 0 auto;">
        <talk-item/>
    </div>
</template>

<script>
import TalkItem from '@/components/Talk/TalkItem.vue'

export default {
    name: 'Talk',
    components: {
        TalkItem
    }
}
</script>

<style>

</style>

TalkItem.vue

<template>
    <div class="talk-item-wrapper">
        <talk-header/>
        <talk-content/>
        <talk-img/>
    </div>
</template>

<script>
import TalkContent from './TalkContent.vue'
import TalkHeader from './TalkHeader.vue'
import TalkImg from './TalkImg.vue'

export default {
    name: 'TalkItem',
    components: {
        TalkHeader,
        TalkContent,
        TalkImg
    }
}
</script>

<style>
    .talk-item-wrapper {
        margin-top: 5px;
        border: 1px solid #eee;
        border-radius: 8px;
        background-color: #fff;
        box-shadow: 0 3px 6px 0 rgb(0 0 0 / 8%);
    }
</style>
TalkContent.vue
<template>
    <div class="talk-content-wrapper">
        <p>
            <span style="font-size:14px;" data-v-488ad047="">Up&amp;Up 的mv  <br/>Nothing is impossible with Photoshop</span>
            <img src="@/images/se.png" class="emoji-img">
        </p>
    </div>
</template>

<script>

export default {
    name: 'TalkContent',
    components: {
    }
}
</script>

<style lang="scss">
    .talk-content-wrapper {
        padding-left: 80px;
        margin-bottom: 8px;
        .emoji-img {
            width: 18px;
            width: 18px;
        }
    }
</style>
TalkHeader.vue
<template>
    <div class="talk-header-wrapper">
        <div class="avatar-wrapper">
            <img src="@/images/avatar.png">
        </div>
        <div class="user-info-wrapper">
            <a href="#" class="nick-name">
                zzhua195
            </a>
            <div class="publish-time">
                2020-06-04 17:33
            </div>
        </div>
        <div class="operation">
            <i class="iconfont icon-24gf-ellipsisVertical"></i>
        </div>
    </div>
</template>

<script>

export default {
    name: 'TalkHeader',
    components: {
    }
}
</script>

<style lang="scss">
.talk-header-wrapper {
    display: flex;
    padding: 10px 10px 0;
    margin-bottom: 5px;

    position: relative;


    .avatar-wrapper {
        width: 50px;
        height: 50px;
        border-radius: 50%;
        overflow: hidden;
        margin-right: 20px;

        img {
            width: 100%;
            height: 100%;
        }

    }

    .user-info-wrapper {
        .nick-name {
            display: block;
            font-size: 16px;
            padding: 6px 0 2px;
        }

        .publish-time {
            font-size: 12px;
            color: #9ea2a9;
        }
    }

    .operation {
        position: absolute;
        right: 6px;
        cursor: pointer;
    }
}</style>
TalkImg.vue
<template>
    <div class="talk-img-wrapper">

        <div class="preview-list" v-show="previewShow">
            <div v-if="imgUrlList.length == 1" :style="oneImgStyleObj">
                <img @click="showSpecifiedImg(0)" :style="oneImgStyleObj" :src="imgUrlList[0]">
            </div>
            <div v-else :class="['preview-box', `grid-` + imgUrlList.length]">
                <img @click="showSpecifiedImg(index)" class="img-item" v-for="(imgUrl, index) in imgUrlList" :src="imgUrl"
                    :key="index">
            </div>
        </div>
        <div class="watch-list" v-show="watchShow">
            <div class="watch-options">
                <div @click="watchOption('shouqi')" class="option-item">
                    <i class="iconfont icon-shouqi"></i>
                    <span>收起</span>
                </div>
                <div @click="watchOption('datu')" class="option-item">
                    <i class="iconfont icon-chakan"></i>
                    <span>查看大图</span>
                </div>
                <div @click="watchOption('zuoxuan')" class="option-item">
                    <i class="iconfont icon-rotate-left"></i>
                    <span>向左旋转</span>
                </div>
                <div @click="watchOption('youxuan')" class="option-item">
                    <i class="iconfont icon-rotate-right"></i>
                    <span>向右旋转</span>
                </div>
            </div>
            <div class="watch-img" :style="{ height: watchImgHeight }">
                <div class="watch-img-prev" @click="changeImg(currWatchImgIndex - 1)"
                    v-show="imgUrlList.indexOf(currWatchImg) != 0">
                    <i class="iconfont icon-xiangyou"></i>
                </div>
                <div class="watch-img-next" @click="changeImg(currWatchImgIndex + 1)"
                    v-show="imgUrlList.indexOf(currWatchImg) != imgUrlList.length - 1">
                    <i class="iconfont icon-xiangyou"></i>
                </div>
                <img id="img1111" :style="currImgStyleObj" ref="currWatchImgRef" :src="currWatchImg">
            </div>
            <div class="watch-track" v-if="imgUrlList.length > 1">
                <div @click="changeImg(index)" :class="['watch-track-item', { 'track-active': currWatchImgIndex == index }]"
                    v-for="(imgUrl, index) in imgUrlList" :key="index">
                    <img :src="imgUrl">
                </div>
            </div>
        </div>
        <div class="action">
            <div class="action-item">
                <i class="iconfont icon-zhuanfa"></i>
                <span>转发</span>
            </div>
            <div class="action-item">
                <i class="iconfont icon-pinglun"></i>
                <span>评论</span>
            </div>
            <div :class="['action-item', { 'isLike': isLike }]" @click="isLike = !isLike">
                <i class="iconfont icon-good"></i>
                <span>点赞</span>
            </div>
        </div>
    </div>
</template>

<script>

import img1 from '@/images/1.png'
import img2 from '@/images/2.png'
import img3 from '@/images/3.png'
import img4 from '@/images/4.png'
import img5 from '@/images/5.png'
import img6 from '@/images/6.png'

import test1_100x1600 from '@/images/test1_100x1600.png'
import test1_1600x100 from '@/images/test1_1600x100.png'
import test2_100x800 from '@/images/test2_100x800.png'
import test2_800x100 from '@/images/test2_800x100.png'
import se from '@/images/se.png'
import img7 from '@/images/7.jpg'
import img8 from '@/images/8.jpg'



export default {
    name: 'TalkImg',
    components: {
    },
    data() {
        return {
            // imgUrlList: [ test2_100x800,test2_800x100, test1_100x1600, test1_1600x100],
            imgUrlList: [img1,img2,img3,img4,img5,img6],
            // imgUrlList: [test1_100x1600,test2_100x800,test2_800x100,img2,se],
            previewShow: true, // 是否显示图片预览
            watchShow: false, // 是否显示图片查看器
            currWatchImg: img1,   // 当前正在查看图片的url
            currWatchImgIndex: 0, // 当前正在查看的图片的索引
            watchImgHeight: '', // 用于查看当前图片的容器的高度-行内样式
            currImgStyleObj: {}, // 当前图片的样式-行内样式
            currImgHeight: null, // 当前图片高度(当前第一次点击此图片时,记录它, 留做参考,不作修改)
            currImgWidth: null, // 当前图片宽度(当前第一次点击此图片时,记录它, 留做参考,不作修改)
            /* 当前正在查看的图片的旋转角度, 只有0 90 180 270 这4种取值  */
            currImgRotateValue: 0,
            isLike: false,
            oneImgStyleObj: { 'border-radius': '4px' }
        }
    },
    mounted() {

        if (this.imgUrlList.length == 1) {
            let img = new Image()
            img.src = this.imgUrlList[0]
            img.onload = () => {
                if (img.width >= 320) {
                    this.$set(this.oneImgStyleObj, 'width', '320px')
                    this.$set(this.oneImgStyleObj, 'height', (320 * img.height / img.width + 'px'))
                }
            }
        }
    },
    methods: {

        showSpecifiedImg(imgIdx) {

            // 修改当前图片的索引
            let imgUrl = this.imgUrlList[imgIdx]
            this.currWatchImgIndex = imgIdx

            // 加载这张图片,目的是为了获取它的宽高,以判别宽度能否放得下这张图片,如果放不下(宽度大于518),则需要调整图片的宽高
            let image = new Image()
            image.src = imgUrl
            console.log(image.width, image.height, 343);

            image.onload = () => {
                // setTimeout(() => {
                    this.currImgHeight = image.height
                    this.currImgWidth = image.width
                    console.log('onload..............', this.currImgHeight, this.currImgWidth, image.width > 518);

                    this.resetWatchImg()

                    // 仅处理图片宽度大于518的情况, 如果图片小于518, 那么对于图片容器的宽度来说, 是能放下这个张图片, 高度就不管了 
                    if (image.width > 518) {
                        // 此时,图片肯定会按比例缩小, 高度也会缩小
                        this.$set(this.currImgStyleObj, 'width', '518px')
                        // 重新记录当前查看的图片的宽高
                        this.currImgWidth = 518
                        this.currImgHeight = 518 * image.height / image.width
                        console.log(this, this.currImgStyleObj, 'currImgStyleObj');
                    }
                
                    this.currWatchImg = imgUrl
                    // 关闭预览,打开图片浏览器
                    this.previewShow = false
                    this.watchShow = true
                // },5000)
            }

        },
        watchOption(optionName) {
            console.log(optionName);
            switch (optionName) {
                case 'shouqi':
                    this.previewShow = true;
                    this.watchShow = false;
                    this.resetWatchImg()
                    break;
                case 'datu':
                    this.$prevImg.open(this.currWatchImgIndex, this.imgUrlList)
                    break;
                case 'youxuan':

                    /* console.dir(this.$refs.currWatchImgRef);
                    console.dir(this.$refs.currWatchImgRef.width);
                    console.dir(this.$refs.currWatchImgRef.height); */

                    if (this.currImgRotateValue == 0 || this.currImgRotateValue == 180) {

                        this.currImgRotateValue += 90

                        // 旋转成水平方向后,须重新计算新的宽高
                        if (this.currImgHeight > 518) {
                            let newCurrImgHeight = 518
                            let newCurrImgWidth = this.currImgWidth / this.currImgHeight * 518
                            // 修改图片行内样式的宽高, 并且旋转
                            this.currImgStyleObj = { width: newCurrImgWidth + 'px', height: newCurrImgHeight + 'px', transform: `rotate(${this.currImgRotateValue}deg)` }

                            // 修改查看图片的容器的高度
                            this.watchImgHeight = newCurrImgWidth + 'px'

                            // 将图片移到图片容器里面去
                            // 变化后的图片它的中心点不和容器的中心点重合,而是变化后的图片中心,图片旋转会以这个中心点做旋转, 
                            // 然后计算让旋转后的图片的左边缘与容器的左边对齐,旋转后的图片的上边缘与容器的上边对齐
                            this.currImgStyleObj.position = "absolute"
                            this.currImgStyleObj.top = (newCurrImgWidth - newCurrImgHeight) / 2 + 'px'
                            this.currImgStyleObj.left = (newCurrImgHeight - newCurrImgWidth) / 2 + 'px'

                        } else {

                            // 现在可以判定,这张图片,在0deg的时候,一定被放下了,
                            // 此时不要再动图片的宽高了,只需动图片容器的宽度,让容器能放下这张图片,并且让图片定位到图片容器中

                            this.watchImgHeight = this.currImgWidth + 'px'

                            this.currImgStyleObj = { width: this.currImgWidth + 'px', height: this.currImgHeight + 'px', transform: `rotate(${this.currImgRotateValue}deg)` }

                            this.currImgStyleObj.position = "absolute"
                            this.currImgStyleObj.top = (this.currImgWidth - this.currImgHeight) / 2 + 'px'
                        }


                    } else if (this.currImgRotateValue == 90 || this.currImgRotateValue == 270) {
                        this.currImgRotateValue += 90
                        // 转到360,就恢复成0度
                        if (this.currImgRotateValue == 360) {
                            this.currImgRotateValue = 0
                        }
                        // 恢复图片的宽度和高度(用第一次记录的), 旋转图片就行了
                        this.currImgStyleObj = { width: this.currImgWidth + 'px', height: this.currImgHeight + 'px', transform: `rotate(${this.currImgRotateValue}deg)` }

                        console.log('currImgStyleObj', this.currImgStyleObj);

                        // 恢复容器的宽度和高度
                        this.watchImgHeight = ''
                    }

                    break;
                case 'zuoxuan':

                    /* console.dir(this.$refs.currWatchImgRef);
                    console.dir(this.$refs.currWatchImgRef.width);
                    console.dir(this.$refs.currWatchImgRef.height); */

                    if (this.currImgRotateValue == 0 || this.currImgRotateValue == 180) {

                        if (this.currImgRotateValue == 0) {
                            this.currImgRotateValue = 270
                        } else {
                            this.currImgRotateValue -= 90
                        }

                        // 旋转成水平方向后,须重新计算新的宽高
                        if (this.currImgHeight > 518) {
                            let newCurrImgHeight = 518
                            let newCurrImgWidth = this.currImgWidth / this.currImgHeight * 518
                            // 修改图片行内样式的宽高, 并且旋转
                            this.currImgStyleObj = { width: newCurrImgWidth + 'px', height: newCurrImgHeight + 'px', transform: `rotate(${this.currImgRotateValue}deg)` }

                            // 修改查看图片的容器的高度
                            this.watchImgHeight = newCurrImgWidth + 'px'

                            // 将图片移到图片容器里面去
                            // 变化后的图片它的中心点不和容器的中心点重合,而是变化后的图片中心,图片旋转会以这个中心点做旋转, 
                            // 然后计算让旋转后的图片的左边缘与容器的左边对齐,旋转后的图片的上边缘与容器的上边对齐
                            this.currImgStyleObj.position = "absolute"
                            this.currImgStyleObj.top = (newCurrImgWidth - newCurrImgHeight) / 2 + 'px'
                            this.currImgStyleObj.left = (newCurrImgHeight - newCurrImgWidth) / 2 + 'px'

                        } else {

                            // 现在可以判定,这张图片,在0deg的时候,一定被放下了,
                            // 此时不要再动图片的宽高了,只需动图片容器的宽度,让容器能放下这张图片,并且让图片定位到图片容器中

                            this.watchImgHeight = this.currImgWidth + 'px'

                            this.currImgStyleObj = { width: this.currImgWidth + 'px', height: this.currImgHeight + 'px', transform: `rotate(${this.currImgRotateValue}deg)` }

                            this.currImgStyleObj.position = "absolute"
                            this.currImgStyleObj.top = (this.currImgWidth - this.currImgHeight) / 2 + 'px'
                        }


                    } else if (this.currImgRotateValue == 90 || this.currImgRotateValue == 270) {

                        this.currImgRotateValue -= 90

                        // 恢复图片的宽度和高度(用第一次记录的), 旋转图片就行了
                        this.currImgStyleObj = { width: this.currImgWidth + 'px', height: this.currImgHeight + 'px', transform: `rotate(${this.currImgRotateValue}deg)` }

                        // 恢复容器的宽度和高度
                        this.watchImgHeight = ''

                    }

                    break;
            }
        },
        changeImg(imgIndex) {
            /* 当前正在查看的图片的旋转角度, 只有0 90 180 270 这4种取值  */
            this.showSpecifiedImg(imgIndex)
        },
        resetWatchImg() {
            this.watchImgHeight = ''
            this.currImgStyleObj = {}
            this.currImgHeight = null
            this.currImgWidth = null
            /* 当前正在查看的图片的旋转角度, 只有0 90 180 270 这4种取值  */
            this.currImgRotateValue = 0
        }
    }
}
</script>

<style lang="scss">
.talk-img-wrapper {
    padding-left: 80px;

    .preview-box {
        display: flex;
        flex-wrap: wrap;

        .img-item {
            width: 104px;
            height: 104px;
            object-fit: cover;
            border-radius: 5px;
            cursor: pointer;
            margin-bottom: 4px;
            margin-right: 4px;
            display: block;
        }
    }

    .grid-9,
    .grid-8,
    .grid-7,
    .grid-6,
    .grid-5,
    .grid-3 {
        width: 327px;
    }

    .grid-4,
    .grid-2 {
        width: 220px;
    }

    .watch-list {
        width: 518px;
        color: #666666;

        .watch-options {
            display: flex;
            height: 32px;
            background: #f4f5f7;
            line-height: 32px;

            .option-item {
                cursor: pointer;

                &:hover {
                    color: #00a1d6;
                }

                padding: 0 15px;

                i {
                    margin-right: 5px;
                    font-size: 14px;
                }

                span {
                    font-size: 12px;
                }
            }


        }

        .watch-img {
            width: 518px;
            position: relative;

            background-color: #f4f5f7;
            overflow: hidden;
            transition: all 0.2s;

            img {
                display: block;
            }

            .watch-img-prev:hover i {
                display: block;
            }

            .watch-img-next:hover i {
                display: block;
            }

            .watch-img-prev,
            .watch-img-next {
                z-index: 99999;
                cursor: pointer;
                position: absolute;
                width: 30%;
                height: 100%;
                display: flex;
                align-items: center;
                justify-content: center;

                i {
                    font-size: 24px;
                    color: #fff;
                    opacity: 0.75;
                    display: none;
                }
            }

            .watch-img-prev {
                left: 0;
                transform: rotate(180deg);
            }

            .watch-img-next {
                right: 0;
            }
        }

        .watch-track {
            width: 518px;
            overflow-x: auto;
            overflow-y: hidden;
            display: flex;
            flex-wrap: nowrap;
            padding-bottom: 2px;

            .watch-track-item {
                width: 54px;
                height: 54px;
                margin-top: 5px;
                border-radius: 4px;
                overflow: hidden;
                margin-right: 4px;
                cursor: pointer;
                flex-shrink: 0;

                position: relative;

                &::before {
                    content: '';
                    position: absolute;
                    width: 100%;
                    height: 100%;
                    top: 0;
                    left: 0;
                    background-color: #000;
                    opacity: 0.3;
                }

                &.track-active::before {
                    opacity: 0;
                }

                img {
                    width: 100%;
                    height: 100%;
                    object-fit: cover;
                }
            }
        }

    }

    .action {
        display: flex;
        color: #99a2aa;

        .action-item {
            width: 98px;
            height: 42px;
            cursor: pointer;

            &:hover {
                color: #00a1d6;
            }

            &.isLike {
                color: #00a1d6;
            }

            i {
                margin-right: 5px;
            }

            i,
            span {
                line-height: 42px;
                font-size: 13px;
            }
        }

    }


}


::-webkit-scrollbar {
    /*滚动条整体样式*/
    width: 10px;
    /*高宽分别对应横竖滚动条的尺寸*/
    height: 5px;
}

::-webkit-scrollbar-thumb {
    /*滚动条里面小方块*/
    border-radius: 10px;
    //background-color: #8c8c8c;
    background-color: rgba(0, 0, 0, 0.25);
}

::-webkit-scrollbar-track {
    background-color: #f6f6f6;
}

::-webkit-scrollbar-thumb,
::-webkit-scrollbar-track {
    border: 0;
}</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值