基于HTML+CSS实现的可交互照片墙Web页面

一、 实验目的

本次实验目为练习 HTML+CSS 的布局与样式,以及简单的交互

二、实验内容

制作一个可交互的照片墙,照片墙可以点击照片查看大图

三、实验步骤

1. 确定需求

照片墙是一个可以将照片按照一定的顺序排列的 Web 页面,基本要求是照片要合理的地排布在页面上,且照片的尺寸要合适,布局要整齐。

点击照片,可以在当前页面上方显示一个新的图层,其中显示这张照片的更大尺寸的图片。点击图层的其它位置可以隐藏该图层

可以向照片墙中添加照片

可以删除照片墙中的照片

可以替换照片墙的照片

页面要具有很好的过渡效果,且满足响应式设计,适应不同尺寸的设备

2.设计页面原型

根据需求,设计界面原型。

上方居中显示标题和作者

主题部分为网格化布局照片,使用空白作为网格线。在正常计算机浏览器上每行显示 4 张图片,默认初始有 12 张图片。在平板电脑(宽度小于 1024px 大于 690px)浏览器上每行显示 3 张图片。在手机(宽度小于 690px)浏览器上每行显示两张图片。且在页面右下位置有一个固定不动的添加图片按钮

底端显示提示信息

大图页面为灰色蒙层,蒙层上为一张图片。在蒙层右下位置有一个删除按钮和一个替换按钮

3. 实现布局

编写 index.html、index、CSS

关键技术:

主页面

Outside_block 中为页面主题部分,其中 title_block 为标题,有两个标题标签组成,photo_block 是图片,由 12 张初始组成,bottom_block 为底端提示,由两个文字标签组成

其中图片布局采用 flex 布局,具体样式为:

对于容器整体,采用多余元素换行显示,水平、竖直以及每行行内竖直均为居中

对于容器内的图片元素,采用百分比宽度 20% 设置图片宽度,同时确保每行显示 4 个图片。

其余样式不再赘述

加号按钮

在 outside_block 外设置一个 div 作为新增图片的按钮,其中放置一个加号的图片。此外还需要添加一个隐藏的组件,用于触发选择文件。因为 div 无法单纯通过点击事件调用选择文件的接口,因此将它的点击事件绑定到可以调用选择文件事件的 input 上。

具体样式为:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BYYpylWT-1654393976212)(https://www.writebug.com/myres/static/uploads/2021/12/18/3a60065e82b9e4d6dfa986424b428cfb.writebug)]

display:none 将 input 隐藏

position:fixed 将元素设为固定布局,固定在页面的某个位置,不随页面的移动而移动。同时设置为为 flex 容器,使其中的“+”号可以位于按钮的中央

大图图层

Big 为图层本身

Big_img 用于存放大图,其 src 为空,动态填入

两个按钮使用 button

Input 作用同上

伪类动作

对所有图片、按钮,使用:hover {cursor: pointer}使的当鼠标悬停时,变为指针

对图片,使用:hover{transform.scale(1.1)}设置鼠标悬停在图片上方时,图片略微放大以指示该图片

对三个按钮,使用:hover{transform: translateY(-4px)}设置鼠标悬停在按钮上方时,按钮向上浮动 4px 的效果

响应式设计

使用了 flex 布局,实现响应式设计

同时在中设置 viewport 视窗,限制移动端的视窗长度

4.实现交互

编写 index.js,使用 jQuery 编写

核心交互功能

添加图片

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y2iT9Esf-1654393976212)(https://www.writebug.com/myres/static/uploads/2021/12/18/d24a689d11ad5f63be618d11513f1a6d.writebug)]

将按钮(.button)的点击事件绑定到隐藏的文件输入上(.button_hidden),并且监听选择文件改变事件 change。

利用 FileReader,对(id=“upload”)选择的文件 file,进行读取,并且使用 src 接收返回的图片 base64 格式编码(存放在 oFRevent.target.result)中。

在将或得到的 src 插入一个标签中,添加到 photo_block 最后

点击查看大图

为所有的图片添加点击事件 show,对于新增的 DOM 节点,由于 JS 的渲染特性为在加载时一次性渲染,因此无法绑定上述事件。使用 on 函数,监听未知 img 节点的点击事件,并绑定响应函数 show。并将触发点击事件的元素 id 存入全局变量中

传入参数为当前被点击的 DOM 对象,show 函数为:

首先获取被点击图片的 src,并将它赋给大图 big_img

再根据当前窗口的大小和图片的尺寸,设置大图的尺寸。若图片是宽大于高,则将宽设置为窗口宽度的 scale 倍,否则将高设置额为窗口高度为 scale 被,并等比例缩放。将新的宽度、高度赋予 big_img,并计算边距,赋予内部 div(.inner)

设置完成后,使用 fadeIn 将大图图层显示出来(“.big”)

对大图图层,设置隐藏函数 fadeOut 响应点击事件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tp8ejuFm-1654393976214)(https://www.writebug.com/myres/static/uploads/2021/12/18/9c87fbb874bd1d3acbfc66257cc94fa1.writebug)]

删除图片:

直接使用 remove 删除。

替换图片:

原理同新增图片,拿到 src 后替换原有 src

四、实验结果

1.界面效果

  1. 添加图片后:

  1. 查看大图

  1. 平板电脑效果:

  1. 手机效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E4ppj7XU-1654393976216)(https://www.writebug.com/myres/static/uploads/2021/12/18/c2ce7955a33a176fe45b16895ba85191.writebug)]

五、实验结论

对于 Web 页面的开发,设计响应式布局是十分重要的

Flex 布局中 align-items 和 align-content 很容与混淆

六、源代码

  1. index.html
<!DOCTYPE html>
<html>

<head>
    <title>Homewor1, XingyuLiu</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <link rel="stylesheet" type="text/css" href="./index.css">
    <script src=".\jquery-3.4.0.min.js"></script>
</head>

<body>
    <div class="button" type="button">
        <img src="./original_img/plus.svg" class="button_img">
    </div>
    <input class="button_hidden" id="upload" accept="image/gif, image/jpeg, image/x-png" type="file">
    <div class="outside_block">
        <div class="title_block">
            <h1 class="title">Homework1:Photo Wall</h1>
            <h5 class="title"> Xingyu Liu 3017218063</h5>
        </div>

        <div class="photo_block">
            <img id="img_1" src="./original_img/1.jpg">
            <img id="img_2" src="./original_img/2.jpg">
            <img id="img_3" src="./original_img/3.jpg">
            <img id="img_4" src="./original_img/4.jpg">
            <img id="img_5" src="./original_img/5.jpg">
            <img id="img_6" src="./original_img/6.jpg">
            <img id="img_7" src="./original_img/7.jpg">
            <img id="img_8" src="./original_img/8.jpg">
            <img id="img_9" src="./original_img/9.jpg">
            <img id="img_10" src="./original_img/10.jpg">
            <img id="img_11" src="./original_img/11.jpg">
            <img id="img_12" src="./original_img/12.jpg">
        </div>

        <div class="bottom_block">
            <span>点击图片可以查看大图,点击加号可以添加图片</br></span>
            <span>CopyRight Liuxingyu 2019.11.26</span>
        </div>
    </div>

    <div class="big">
        <div class="inner">
            <img id="big_img" src="" />
            <button class="delete">删除</button>
            <button class="replace">替换</button>
            <input class="replace_hidden" id="replace" accept="image/gif, image/jpeg, image/x-png" type="file">
        </div>
    </div>

    <script type="text/javascript" src="./index.js"></script>
</body>


</html>
  1. index.css
* {
    margin: 0;
    box-sizing: border-box;
    transition: all .4s;
}

body {
    background-color: rgb(224, 224, 224);
}

.outside_block {
    max-width: 100%;
    min-height: 100%;
    padding: 30px 10% 30px 10%;
}

.title {
    text-align: center;
}

.photo_block {
    display: flex;
    justify-content: center;
    align-content: center;
    align-items: center;
    flex-wrap: wrap;
}

.photo_block img {
    box-shadow: 4px 4px rgba(87, 87, 87, 0.349);
    border-radius: .5em;
    margin: 25px 2%;
    width: 200px;
    border-radius: .5em;
}

.photo_block img:hover {
    transform: scale(1.1);
    transition: all .2s;
}

.bottom_block {
    font-size: 12px;
    color: rgb(136, 136, 136);
    text-align: center;
}

.button_hidden,
.replace_hidden {
    display: none;
}

.button,
.delete,
.replace {
    background-color: rgb(211, 162, 0);
    position: fixed;
    top: 70%;
    right: 10%;
    width: 50px;
    height: 50px;
    border-radius: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
}

.replace {
    top: 80%;
}


/* 悬停,按钮上浮动 */

.button:hover {
    box-shadow: 0 10px 13px 0 rgba(1, 1, 3, 0.15);
    transform: translateY(-4px);
}

.button_img {
    width: 30px;
    height: 30px;
}

img:hover {
    cursor: pointer;
}

.big {
    position: fixed;
    top: 0;
    left: 0;
    background: rgba(0, 0, 0, 0.7);
    z-index: 2;
    width: 100%;
    height: 100%;
    display: none;
}

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

.img_block {
    display: flex;
}

button{
    border: none;
    outline: none;
}
  1. index.js
$(function() {
    var num = 12;
    var id = null;

    //新增图片
    //将button点击事件绑定到具有file类型的input上,实现点击button选择文件
    $('.button').click(function() {
        $(".button_hidden").click();
    });

    //filereader获取文件base64编码,填充到一个新<img>标签中
    $(".button_hidden").change(function() {
        var oFReader = new FileReader();
        var file = document.getElementById('upload').files[0]; //获取选择的文件对象
        oFReader.readAsDataURL(file); //解析为base64
        oFReader.onloadend = function(oFRevent) {
            var src = oFRevent.target.result; //解析后的base64编码值
            if (src !== null) {
                num = num + 1;
                var photo_block = $(".photo_block");
                photo_block.append("<img id='img_" + num + "' src='" + src + "'>"); //赋予一个新的<Img>对象,并为之添加新ID编号
            } else {
                alert("文件出错")
            }
        }
    })

    //监听所有图片以及可能尚未添加的<img>标签,并且显示大图
    $(".photo_block").on("click", "img", function() {
        id = $(this).attr("id");
        show(this);
    })

    //隐藏大图
    $(".big").click(function() {
        $(this).fadeOut("fast");
    })

    //显示大图
    function show(picture) {
        var src = $(picture).attr("src");

        //填充大图src
        $("#big_img").attr("src", src);

        //缩放图片。如果图片长>宽,则长边变为屏幕宽度的scale比例,如果此时高度大于屏幕高度
        //则再将高度缩放scale比例。反之同理
        var scale = 0.7;
        var windowW = $(window).width();
        var windowH = $(window).height();
        var realWidth = picture.width;
        var realHight = picture.height;
        var newHeight, newWidth;
        if (realWidth > realHight) {
            newWidth = windowW * scale;
            newHeight = newWidth * realHight / realWidth;
            if (newHeight > realHight) {
                let temp = newHeight;
                newHeight = newHeight * scale;
                newWidth = newHeight * newWidth / temp;
            }
        } else {
            newHeight = windowH * scale;
            newWidth = newHeight * realWidth / realHight;
            if (newHeight < realHight) {
                let temp = newWidth;
                newWidth = newWidth * scale;
                newHeight = newWidth * newHight / temp;
            }
        }

        var padding_top = (windowH - newHeight) / 2;
        var padding_left = (windowW - newWidth) / 2;

        $("#big_img").css("width", newWidth); //以最终的宽度对图片缩放        
        $(".inner").css("padding-top", padding_top);
        $(".inner").css("padding-left", padding_left);
        $(".big").fadeIn("fast");
    }

    //删除
    $(".delete").click(function() {
        $("#" + id).remove();
    })

    //替换
    $(".replace").click(function() {
        $(".replace_hidden").click();
    })

    //替换,读取图片信息并替换已有DOM,方法同新增
    $(".replace_hidden").change(function() {
        var oFReader = new FileReader();
        var file = document.getElementById('replace').files[0];
        oFReader.readAsDataURL(file);
        oFReader.onloadend = function(oFRevent) {
            var newsrc = oFRevent.target.result;
            if (newsrc !== null) {
                $("#" + id).attr("src", newsrc)
            } else {
                alert("文件出错")
            }
        }
    })

})

猜你喜欢

转载自blog.csdn.net/newlw/article/details/125129045