Taro+vue3 实现电影切换列表

news2024/11/16 0:39:27

1.需求

 我们在做类似于猫眼电影的小程序或者H5 的时候 我们会做到那种 左右滑动的电影列表,这种列表一般带有电影场次 

2.效果

3.说明

 这种效果在淘票票 猫眼电影上 都有的 ,一般电影类型的H5 或者小程序 这个是都有的 第一是好看 第二是客观性比较好

4.代码、

1.整体页面
<template>
    <div class="movie-container-index">
        <Header></Header>
        <div class="swiper-main">
            <image class="background-img-vague" :src="chooseMovice.posterUrl" style="height: 100%;"></image>
            <div class="wrap">
                <MovieList :list="movieList" @onchangeMovie="MovieChange" :model-value="chooseMovice.movieId"></MovieList>
            </div>
            <div class="box"></div>

        </div>
        <div class="movie-detail">
            <div class="name">{{ chooseMovice.movieName }}</div>
            <div class="center-detail">
                <div>{{ chooseMovice.movieType }}</div>
                <div>{{ chooseMovice.duration }}</div>

            </div>
            <div class="cast">{{ chooseMovice.cast }}</div>

        </div>
        <div class="movie-time-container">
            <Filter v-if="timeList.length" :data="timeList" @onChanged="onTimeChanged"></Filter>
        </div>
        <div class="movie-arrgement-container" v-if="arrangementList.length && !loading">
            <Item v-for="(item, index) in arrangementList" :info="item" :key="index"></Item>
        </div>
        <template v-if="arrangementList.length === 0 && loading">
            <div style="padding:  0 15px;">
                <nut-skeleton :style="{ width: '100%', margin: '0.5rem 0' }" width="100%" height="15px" title animated
                    row="1">
                </nut-skeleton>
                <nut-skeleton :style="{ width: '100%', margin: '0.5rem 0' }" width="100%" height="15px" title animated
                    row="1">
                </nut-skeleton>
                <nut-skeleton :style="{ width: '100%', margin: '0.5rem 0' }" width="100%" height="15px" title animated
                    row="1">
                </nut-skeleton>
                <nut-skeleton :style="{ width: '100%', margin: '0.5rem 0' }" width="100%" height="15px" title animated
                    row="1">
                </nut-skeleton>
                <nut-skeleton :style="{ width: '100%', margin: '0.5rem 0' }" width="100%" height="15px" title animated
                    row="1">
                </nut-skeleton>
                <nut-skeleton :style="{ width: '100%', margin: '0.5rem 0' }" width="100%" height="15px" title animated
                    row="1">
                </nut-skeleton>
                <nut-skeleton :style="{ width: '100%', margin: '0.5rem 0' }" width="100%" height="15px" title animated
                    row="1">
                </nut-skeleton>
                <nut-skeleton :style="{ width: '100%', margin: '0.5rem 0' }" width="100%" height="15px" title animated
                    row="1">
                </nut-skeleton>
                <nut-skeleton :style="{ width: '100%', margin: '0.5rem 0' }" width="100%" height="15px" title animated
                    row="1">
                </nut-skeleton>
                <nut-skeleton :style="{ width: '100%', margin: '0.5rem 0' }" width="100%" height="15px" title animated
                    row="1">
                </nut-skeleton>
            </div>
        </template>
        <template v-if="arrangementList.length === 0 && !loading">
            <nut-empty description="暂无场次"></nut-empty>
        </template>


    </div>
</template>
<script setup>
import Header from './header.vue'
import MovieList from './movie-list.vue'
import Filter from './filter.vue'
import { ref, reactive, onMounted } from 'vue'
import Item from './item.vue'
const chooseMovice = ref({
    movieId: 12343,
    duration: 149,
    movieType: '剧情|历史|战争',
    cast: '吴京 易烊千玺 段奕宏 张涵予 朱亚文',
    posterUrl: "https://gw.alicdn.com/i1/O1CN01sSmj2b1daSm6IAUcs_!!6000000003752-0-alipicbeacon.jpg_480x480Q30s150.jpg",
    movieName: '长津湖之水门桥',


})
const timeList = ref(["2024-01-09", "2024-01-10", "2024-01-13"])
const arrangementList = ref([])
const loading = ref(true)
const movieList = ref([
    {
        movieId: 12343,
        duration: 149,
        movieType: '剧情|历史|战争',
        cast: '吴京 易烊千玺 段奕宏 张涵予 朱亚文',
        movieName: '长津湖之水门桥',
        posterUrl: "https://gw.alicdn.com/i1/O1CN01sSmj2b1daSm6IAUcs_!!6000000003752-0-alipicbeacon.jpg_480x480Q30s150.jpg"
    },
    {
        cast: "易烊千玺 田雨 陈哈琳 齐溪 公磊 许君聪 王宁 黄尧 巩金国",
        duration: 106,
        movieId: 147885,
        movieName: "奇迹·笨小孩",
        movieType: "剧情",
        posterUrl: "https://gw.alicdn.com/i1/O1CN013Ggc2s1Z8HwrwxAfn_!!6000000003149-0-alipicbeacon.jpg_480x480Q30s150.jpg"
    },
    {
        cast: "张译,李晨,魏晨,曹炳琨,王骁,张子贤,杨新鸣",
        duration: 106,
        movieId: 147886,
        movieName: "三大队",
        movieType: "剧情,犯罪",
        posterUrl: "https://gw.alicdn.com/i4/O1CN01zQvWon1SuCCkUXTr8_!!6000000002306-0-alipicbeacon.jpg_480x480Q30s150.jpg"
    },
    {
        cast: "岑珈其,梁朝伟,刘德华,蔡卓妍,任达华,陈家乐,白只,姜皓文,方中信,太保,钱嘉乐,周家怡",
        duration: 106,
        movieId: 147887,
        movieName: "金手指",
        movieType: "犯罪,剧情",
        posterUrl: "https://gw.alicdn.com/i4/O1CN01mdCwok1K4QV7FV8gv_!!6000000001110-0-alipicbeacon.jpg_480x480Q30s150.jpg"
    },
    {
        cast: "李栋,大鹏,白客,庄达菲,王迅,孙艺洲,李乃文",
        duration: 106,
        movieId: 147888,
        movieName: "年会不能停!",
        movieType: "喜剧,剧情",
        posterUrl: "https://gw.alicdn.com/i1/O1CN01v6g8341QMBaLa2FhI_!!6000000001961-0-alipicbeacon.jpg_480x480Q30s150.jpg"
    },
    {
        cast: "屈楚萧,张佳宁,傅菁,蒋昀霖,牛超,田壮壮,沙溢",
        duration: 106,
        movieId: 147889,
        movieName: "一闪一闪亮星星",
        movieType: "爱情,奇幻",
        posterUrl: "https://gw.alicdn.com/i4/O1CN01W8mzt61aa3k1Xtw3N_!!6000000003345-0-alipicbeacon.jpg_480x480Q30s150.jpg"
    },
    {
        cast: "江户川柯南,高山南,山崎和佳奈,小山力也,林原惠美,置鲇龙太郎,三石琴乃,土师孝也,乃村健次,飞田展男,绪方贤一,松井菜樱子,岩居由希子,大谷育江,茶风林",
        duration: 106,
        movieId: 147890,
        movieName: "名侦探柯南:黑铁的鱼影",
        movieType: "动画,悬疑,动作",
        posterUrl: "https://gw.alicdn.com/i1/O1CN01U9wWR81pfku0aqB6O_!!6000000005388-0-alipicbeacon.jpg_480x480Q30s150.jpg"
    }

])
const MovieChange = (e) => {
    console.log(e);
    chooseMovice.value = movieList.value.filter((item) => item.movieId == e)[0]

}
onMounted(() => {
    arrangementList.value = [
        {
            finishTime: "1704782520000",
            hallName: "7号激光杜比全景声厅",
            id: "1194219979173253121",
            pickUpPrice: 3380,
            price: 3500,
            showTime: "1704775500000"
        }
    ]
    loading.value = false
})
</script>
<style lang="scss">
.movie-container-index {
    display: flex;
    flex-direction: column;

    .movie-arregment-container {}


    .swiper-main {
        height: 324px;
        position: relative;
        overflow: hidden;
        width: 100%;

        .background-img-vague {
            position: absolute;
            left: 0;
            right: 0;
            width: 100%;
            height: 100%;
            filter: blur(15px);
            -webkit-filter: blur(15px);
        }
    }

    .movie-detail {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        background-color: #fff;
        padding: 20px;

        .name {
            font-size: 30px;
            font-weight: 700;
            color: #15181d;

        }

        .center-detail {
            display: flex;
            align-items: center;
            color: #858a99;
            font-size: 24px;
            margin-top: 5px;

        }

        .cast {
            color: #858a99;
            font-size: 24px;
            margin-top: 5px;
            word-break: break-all;
            text-align: center;
            overflow: hidden;
            display: -webkit-box;
            -webkit-line-clamp: 2;
            -webkit-box-orient: vertical;

        }
    }



    .wrap {
        padding: 10px 0;


    }

    .box {
        width: 0;
        height: 0;
        border: 10rpx solid;
        border-color: transparent transparent #fff #fff;
        transform: rotate(135deg);
        position: absolute;
        bottom: -10rpx;
        left: 0;
        right: 0;
        margin: 0 auto;
    }
}
</style>
2.movie-list代码


<template>
    <div class="movie-list-component">
        <div class="list-container">
            <scroll-view id="contentScroll" class="scroll-view" :scroll-with-animation="true" :scroll-left="scrollLeft"
                :scroll-x="true">
                <div class="movie-item seat"></div>
                <div :data-id="item.movieId" @click="selectMovie" :id="`movieItem${item.movieId}`" class="movie-item" 
                    :class="{ active: modelValue == item.movieId }" v-for="( item, index ) in  list " :key="index">
                    <div class="img-container">
                        <image class="img" :src="item?.posterUrl" alt="" />
                    </div>
                </div>
                <div class="movie-item seat1"></div>
            </scroll-view>
        </div>
    </div>
</template>
<script setup lang="ts">
import Taro from "@tarojs/taro";
import { onMounted, ref, reactive, toRefs, watch } from "vue";
const props = defineProps({
    // 子组件接收父组件传递过来的值
    list: {
        type: Array<any>,
        required: true,
    },
    modelValue: {
        type: Number,
        required: true,
    },
});
//使用父组件传递过来的值
const { list, modelValue } = toRefs(props);
const emit = defineEmits(["onchangeMovie"]);

onMounted(() => {
    // selectMovie(list.value[0].movieId)
    list?.value.map((item, index) => {
        if (item.id === modelValue?.value) {
            list?.value.unshift(list?.value.splice(index, 1)[0]);
        }
    });

});
const scrollLeft = ref(0);
//选择电影
const selectMovie = (e) => {
    let offsetLeft = e.currentTarget.offsetLeft;
    let { id } = e.currentTarget.dataset;
    if (!id) {
        id = list.value[0].movieId;
    }
    if (modelValue.value == id) {
        return;
    }
    emit("onchangeMovie", id);
    getRect(id, offsetLeft);
};
//计算电影item的偏移量
const getRect = async (id, offsetLeft) => {

    const eleId = `#movieItem${id}`;

    const contentScrollWidth: any = await getContentScrollWidth("#contentScroll");
    const query = Taro.createSelectorQuery();
    query.select(eleId).boundingClientRect();
    query.selectViewport().scrollOffset();
    query.exec(async (res) => {

        //获取item的宽度de 一半
        const subhalfwidth = res[0].width / 2;
        //需要scrollview 移动的距离是
        const juli = offsetLeft - contentScrollWidth / 2 + subhalfwidth;
        scrollLeft.value = juli;

    });
};
// 获取ScrollView的宽度
const getContentScrollWidth = (ele) => {
    return new Promise((resolve) => {
        const query = Taro.createSelectorQuery();
        query.select(ele).boundingClientRect();
        query.selectViewport().scrollOffset();
        query.exec((res) => {
            const width = res[0].width;
            resolve(width);
        });
    });
};
</script>
<style lang="scss">
.movie-list-component {
    display: flex;
    flex-direction: column;

    .list-container {
        display: flex;
        flex-direction: column;
        justify-content: center;
        height: 324px;

        .scroll-view {
            width: 100%;
            height: 324px;
            white-space: nowrap;
            position: relative;

            .movie-item:nth-child(n+2) {
                margin-left: 35px;
            }

            .movie-item {
                display: inline-block;
                position: relative;

                margin-top: 30px;
                border-radius: 18px;
                width: 156px;
                height: 218px;
                // line-height: 208px;
                transition: width 1s;
                transition: height 1s;

                .img-container {
                    border-radius: 8px;
                    width: 100%;
                    height: 100%;
                    overflow: hidden;
                    position: relative;
                    z-index: 2;
                    // border: 5px #ffffff solid;

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

            .movie-item.active {
                transform: scale(1.15);
                /* 放大1.2倍 */
                transition: transform 1s ease;
                /* 过渡效果 */
            }

            .seat {
                display: inline-block;
                width: 50%;
                // height: 290px;
                margin-left: -110px;
            }

            .seat1 {
                display: inline-block;
                width: 35%;
            }
        }
    }
}
</style>
filter 组件

<template>
    <div class="cinema-detail-filter-container">
        <div class="date-tab">
            <nut-tabs :title-gutter="15" v-model="tabTimesIndex" title-scroll>
                <nut-tab-pane v-for="(item, index) in tabTimesList" :pane-key="index" :title="`${item.t} ${item.a}`">
                </nut-tab-pane>
            </nut-tabs>
        </div>
    </div>
</template>
<script setup lang="ts">
import { computed, onMounted, ref, toRefs, watch } from 'vue';
import moment from "moment";
const tabTimesIndex = ref(0)
const tabTimesList: any = ref([])
const props = defineProps({
    //子组件接收父组件传递过来的值
    data: Object,
});
//使用父组件传递过来的值
const { data: timesList } = toRefs(props);
onMounted(() => {
    getTimes()
});
const emit = defineEmits(['onChanged'])
watch(tabTimesIndex, (index) => {
    emit('onChanged', tabTimesList.value[index])
})
watch(tabTimesList, () => {
    emit('onChanged', tabTimesList.value[0])
})
const getTimes = () => {
    const times = timesList?.value
    
    const arr: any = []
    times?.forEach(item => {
        const time = item
        let t = getweek(moment(time).startOf('day').format('E'))
        if (time === moment().format('YYYY-MM-DD')) {
            t = '今天'
        } else if (time === moment().subtract(-1, 'days').format('YYYY-MM-DD')) {
            t = '明天'
        } else if (time === moment().subtract(-2, 'days').format('YYYY-MM-DD')) {
            t = '后天'
        }
        arr.push({
            time: time,
            t: t,
            a: time.substr(5, 9)
        })
    });
    tabTimesList.value = arr

}
const getweek = (val) => {
    const week = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
    return week[val - 1];
};
</script>
<style lang="scss">
.cinema-detail-filter-container {
    display: flex;
    flex-direction: column;

    .nut-tabs {
        .nut-tabs__titles {
            background: #ffffff !important;

            .nut-tabs__titles-item {
                .nut-tabs__titles-item__smile {
                    display: none;
                }

                .nut-tabs__titles-item__text {
                    color: #858a99;
                    font-size: 22px !important;

                }
            }

            .nut-tabs__titles-item__line {
                background: linear-gradient(to right, #5232B7, #7237BC, #5232B7) !important;
                border-radius: 30px !important;
            }

            .nut-tabs__titles-item.active {
                .nut-tabs__titles-item__smile {
                    display: block;
                    margin-top: 10px;
                }

                .nut-tabs__titles-item__text {
                    color: #15181d;
                }
            }
        }

        .nut-tabs__content {
            display: none !important;
        }
    }
}
</style>
header 组件

<template>
    <div class="movie-header-box">
        <div class="left">
            <div class="name">万达影城(北京昌平保利光魔店)</div>
            <div class="address">昌平区鼓楼街贾琏时代广场四楼</div>

        </div>
        <div class="right">
            <IconFont name="locationg3" color="#5232B7"></IconFont>
        </div>
    </div>
</template>
<script setup>
import { IconFont } from '@nutui/icons-vue-taro';
</script>
<style lang="scss">
.movie-header-box {
    display: flex;
    align-items: center;
    justify-content: space-between;
    background-color: #fff;
    padding: 25px 30px;

    .left {
        .name {
            color: #15181d;
            font-weight: 700;
            font-size: 26px;
        }

        .address {
            color: #858a99;
            font-size: 22px;
            margin-top: 10px;
        }
    }
}
</style>

5.我这个项目是基于Taro +vue3 +ts 来写的 用的组件库也是京东的nut-ui  以上的代码和组件 也有的是我二次封装的组件 组件也挺方便的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1369271.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

动态规划python简单例子-斐波那契数列

def fibonacci(n):dp [0, 1] [0] * (n - 1) # 初始化动态规划数组for i in range(2, n 1):dp[i] dp[i - 1] dp[i - 2] # 计算斐波那契数列的第 i 项print(dp)return dp[n] # 返回斐波那契数列的第 n 项# 示例用法 n 10 # 计算斐波那契数列的第 10 项 result fibonac…

llama.cpp模型推理之界面篇

目录 前言 一、llama.cpp 目录结构 二、llama.cpp 之 server 学习 1. 介绍 2. 编译部署 3. 启动服务 4、扩展或构建其他的 Web 前端 5、其他 前言 在《基于llama.cpp学习开源LLM本地部署》这篇中介绍了基于llama.cpp学习开源LLM本地部署。在最后简单介绍了API 的调用方…

智汇云舟受邀出席《城市轨道交通公共安全防范安全评价标准》专家评审会

1月3日&#xff0c;由中国城市公共交通协会归口的《城市轨道交通公共安全防范安全评价标准》&#xff08;以下简称“《标准》”&#xff09;送审稿审查会顺利召开。该标准由同方威视技术股份有限公司、上海新海信通信息技术有限公司和中安保实业集团有限公司主编&#xff0c;北…

Java常用类---包装类

包装类 包装类简介 Java语言是典型的面向对象编程语言&#xff0c;但是其中的8种基本数据类型并不支持面向对象编程&#xff0c;基本类型数据不具备"对象"的特性&#xff0c;即&#xff1a;没有携带属性以及没有方法可以调用。 为了解决上述问题&#xff0c;java为…

类与对象中篇

前言 在上篇我们讲解了类与对象的基础框架&#xff0c;中篇我们将讲解类与对象的基本内容&#xff0c;即类的六个默认成员函数。 一、类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。 问题&#xff1a; 空类中真的什么都没有吗&#xff1f; 答案是&a…

解读 Sobit v2:铭文资产跨链更注重安全、易用性

铭文市场的发展正在从早期的“无序”进入到“有序”阶段&#xff0c;我们看到从 12 月份以来&#xff0c;比特币生态内的多个应用纷纷宣布获得融资。这表明&#xff0c;目前仍旧有大量的资金有意向铭文领域&#xff0c;同样铭文赛道新一轮浪潮或许正在酝酿。 另一方面&#xff…

HarmonyOS 编写副标题 解决 ubTitle 可能淘汰问题

目前 harmonyos 中 title属性目前用的还正常 但是ubTitle副标题 会提示我们 可能要淘汰了 虽然说 我们目前 强行用 还是可以生效 但可能 哪天版本更新移除了这个属性 代码就报错了 我们可以通过Builder 来写这个副标题 和 标题 Entry Component struct Index {build() {Row(…

ssm基于WEB的文学网的设计与实现+vue论文

基于WEB的文学网的设计与实现 摘要 如今&#xff0c;科学技术的力量越来越强大&#xff0c;通过结合较为成熟的计算机技术&#xff0c;促进了学校、医疗、商城等许多行业领域的发展。为了顺应时代的变化&#xff0c;各行业结合互联网、人工智能等技术&#xff0c;纷纷开展了管…

Linux的网络配置命令和网络设置实操

目录 一、网路命令 1.ifconfig 2.hostname 3.route 4.netstat 5.ss&#xff08;socket statistics&#xff09; 6.ping 7.nslookup 8.tcpdump 二、实操 1.单个网卡修改 2.双网卡配置 3.bond网卡绑定 一、网路命令 查看Linux基础的网络设置 网关route -nIP地址ifc…

python进阶 -- 日志装饰器详解

日志 日志&#xff1a;记录程序运行的时候&#xff0c;出现的问题&#xff0c;或者说验证流程是否正常 在实际工作中&#xff0c;python的脚本命令一般是放在服务器执行的linux系统 日志其实就是记录程序运行时出现的问题、或者正常的打印&#xff0c;协助出现问题的时解决排查…

[书生·浦语大模型实战营]——基于 InternLM 和 LangChain 搭建你的知识库

0. 背景知识 0.1 InternLM InternLM 是一个开源的轻量级训练框架&#xff0c;旨在支持大模型训练而无需大量的依赖。通过单一的代码库&#xff0c;它支持在拥有数千个 GPU 的大型集群上进行预训练&#xff0c;并在单个 GPU 上进行微调&#xff0c;同时实现了卓越的性能优化。…

分析一个项目(微信小程序篇)二

目录 首页&#xff1a; 发现&#xff1a; 购物车&#xff1a; 我的&#xff1a; 分析一个项目讲究的是如何进行对项目的解析分解&#xff0c;进一步了解项目的整体结构&#xff0c;熟悉项目的结构&#xff0c;能够知道每个组件所处在哪个位置&#xff0c;发挥什么作用。 接…

CRM系统是否适合企业,有哪些判断标准?

现如今&#xff0c;以客户为中心不再是一句空话&#xff0c;哪个企业能与客户建立长久的关系&#xff0c;那它就能获得业绩的增长。CRM管理系统的初衷就是维护客户关系&#xff0c;通过深入了解客户&#xff0c;提高转化率&#xff0c;并推动业绩增长。企业在选型时&#xff0c…

游戏引擎巨头Unity 裁员 25%;章泽天净资产600亿;恒大汽车刘永灼被抓;抖音将“抖币”更名为“钻石”;董宇辉新账号将于今晚首播

今日精选 • 游戏引擎巨头 Unity 计划裁员 25%&#xff0c;去年底曾关闭全球多处办公室• 恒大汽车刘永灼被抓&#xff0c;股价闪崩20%&#xff0c;刚丢35亿救命钱• 抖音将“抖币”更名为“钻石”• 章泽天登胡润财富榜&#xff1a;净资产600亿• 董宇辉新账号未开播已有400万…

React Native集成到现有原生应用

本篇文章以MacOS环境开发iOS平台为例&#xff0c;记录一下在原生APP基础上集成React Native React Native中文网 详细介绍了搭建环境和集成RN的步骤。 环境搭建 必须安装的依赖有&#xff1a;Node、Watchman、Xcode 和 CocoaPods。 安装Homebrew Homebrew是一款Mac OS平台下…

【QT-UI】

1.使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 #include "mainwindow.h" #include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), …

36-javascript输出方式,弹框:普通,confirm弹框,prompt弹框,控制台输出:普通,warm,error

1.页面打印 <body><p>你真是一个小机灵鬼</p><script>// 页面打印document.write("打印内容");</script> </body> 2.覆盖文档 <body><p>你真是一个小机灵鬼</p><script>// 覆盖文档window.onload f…

TinkerBoard2跑BuildRoot

我的主板没有EMMC&#xff0c;只能烧录到TF卡 3.1、格式化TF卡 使用$ sudo fdisk -l查看设备&#xff0c;找到对应的设备路径&#xff0c;如/dev/sdd 使用$ sudo fdisk /dev/sdd命令格式化 d //删除分区 n //新建分区 3.2、使用SD_Firmware_Tool烧录固件 我用的是SD_Firmwar…

Spring——Spring整合MyBatis

Spring整合MyBatis 1.创建工程 1.1.pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"…

R语言频率分布直方图绘制教程

本篇笔记分享R语言绘制直方图的方法&#xff0c;通过多种展示风格对数据进行可视化&#xff0c;主要用到ggplot、ggpubr等包。 什么是直方图&#xff1f; 直方图(Histogram)&#xff0c;又称质量分布图&#xff0c;是一种统计报告图&#xff0c;由一系列高度不等的柱子表示数…