图片“瀑布流”显示效果的实现

项目文件

项目文件在我的码云私库:https://gitee.com/huoyingwhw/OldSite

效果如下

实现的思路

1:后台的数据是用DRF从数据库中拿到并且构建成相应的格式——DRF拿到存储展示图片的数据库的表的所有对象,用自己的序列化器以及分页器在后端构建数据结构;

2:前端用JS代码实现,用ajax向后段DRF请求数据,拿到请求的数据后在前端实现“瀑布流”的信息展示效果。

实现的过程详述

一定要记得注册

本功能用到了rest_framework与django-filter,需要在settings的INSTALLED_APPS中注册一下:

INSTALLED_APPS = [
    
     xxxxxx     
   
    'rest_framework',
    'django_filters',
]

Model

本功能只设计图片的展示,因此只设计一个存储图片数据以及图片分类的Model。

class FeedBack(models.Model):

    type_choices = (
        (0,'未分类'),
        (1,'学习笔记'),
        (2,'学员评价'),
        (3,'入职邀约'),
    )

    img = models.ImageField(verbose_name='图片',upload_to='img/feedback/')
    back_type = models.IntegerField(choices=type_choices,verbose_name='分类',default=0)

注意:

(1)图片用ImageField类型存储;

(2)需要先进行Django的media配置(见这篇博客),upload_to要写“相对路径”!图片实际存放的“根”路径是项目的media文件夹(如果media配置是这么配的话),存放在:media/img/feedback/目录下。

(3)back_type用choices,表示文章分类——体现在前端就是:不同的选项卡显示不同类型的图片。

路由配置

这部分功能的路由配置:

# 学习笔记、学员评价、入职邀约用一个路由去处理——这三个功能放在选项卡中展示~
url(r'^(learning-notes|student-evaluation|work-invitation)\.html/$',feedback.feedback_list,name='feedback'),

# ajax_feedback————DRF构建数据与返回数据的路由
url(r'^ajax_feedback/$', feedback.AjaxFeedback.as_view(), name='ajax_feedback'),

(1)主要用两条路由:一个是展示页面的路由——注意这里用分组的方式匹配三个不同的路由:因为前端需要展示三个不同的选项卡;

   另外一条路由是DRF构建数据返回数据的路由——后面ajax向后端请求数据的路由就是它!

(2)将两部分的视图函数写在了同一个py文件中:feedback.py。

(3)由上面可知:三个选项卡的视图是FBV模式,DRF的视图是CBV模式的。

视图函数以及DRF序列化器与分页器的配置

这部分功能的视图函数如下——feedback.py:

# -*- coding:utf-8 -*-
from django.shortcuts import render
from rest_framework import generics
from django_filters.rest_framework import DjangoFilterBackend

from repository import models
from web.serializers import FeedbackSerializer
from web.pagination import DefaultPagination


# 利用table参数去区分不同的页面
# table的值就是下面的字典 feedback_dict 的key中的一个值~~
def feedback_list(request,table): feedback_dict = { 'learning-notes': {'banner': 'images/classmate-say/classmate-banner1.jpg', 'title': '学习笔记'}, 'student-evaluation': {'banner': 'images/classmate-say/classmate-banner2.jpg', 'title': '学员评价'}, 'work-invitation': {'banner': 'images/classmate-say/classmate-banner3.jpg', 'title': '入职邀约'}, } return render(request,'oldboy/pages/classmate-say/feedback.html', {'table':table,'banner':feedback_dict[table]['banner'],'title':feedback_dict[table]['title']}) # feedback————DRF的视图 class AjaxFeedback(generics.ListAPIView): queryset = models.FeedBack.objects.all() serializer_class = FeedbackSerializer pagination_class = DefaultPagination filter_backends = [DjangoFilterBackend,] filter_fields = ['back_type']

视图函数与路由对应,第一个是返回三个选项卡页面的视图,另外一个是DRF的CBV模式的视图函数——注意它的写法,我们在此之前还写了DRF的一个序列化的类与一个分页类~

序列化类—serializers.py文件中的FeedbackSerializer类(也可以创建一个serializers目录,把类写在里面的__init__.py文件中)

# -*- coding:utf-8 -*-
from rest_framework import serializers
from repository import models


class FeedbackSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.FeedBack
        fields = ['img']

分页类—pagination.py文件中的DefaultPagination类(也可以创建一个pagination目录,把类写在里面的__init__.py文件中)

# -*- coding:utf-8 -*-
from rest_framework.pagination import PageNumberPagination

class DefaultPagination(PageNumberPagination):
    page_size = 8  # 一页多少条数据
    page_query_param = 'page'  # 分页查询条件的key
    page_size_query_param = 'size'
    # max_page_size = 8

——之所以创建这个分页类,其实还是为了实现“瀑布流”的效果:前端向后台请求数据的时候,后台“一页一页的把数据传给前端”,前端先显示一页的数据,然后在记录一下页面滑轮滚动的位置,到达页面底端某个位置后再次向后台请求下一页的数据~~以此类推,直到后台把所有的数据都传完为止。

feedback.html文件内容如下

{% extends 'base.html' %}

{% load static %}

{% block css %}
    <link rel="stylesheet" href="{% static 'classmate-say/learning-notes.css' %}">
    <!-- 点击图片放大-->
    <link rel="stylesheet" href="{% static 'oldboy/styles/magnific-popup.css' %}">
    <!-- 瀑布流css -->
    <link rel="stylesheet" href="{% static 'oldboy/styles/salvattore.css' %}">
{% endblock %}

{% block main %}
    <div class="main">
        <div class="banner">
            {# 用传过来的banner值找对应的图片 #}
            <img src="{% static banner %}" alt="">
        </div>
        <ul class="classmate-nav">
            {# 给每个选项卡的a标签加上请求的路径与参数 #}
            <a href="{% url 'web:feedback' 'learning-notes' %}">
                {# 判断一下:如果传过来的table值是当前的标签的值,就加上 thisli 的效果 #}
                <li class="{% if table == 'learning-notes' %}thisli{% endif %}" back_type="1">

                    <img src="{% static 'oldboy/images/classmate-say/classmate-say-icon1.jpg' %}" alt="">
                    <img src="{% static 'oldboy/images/classmate-say/classmate-say-icon1-1.jpg' %}" alt="">
                    <span>学习笔记</span>
                </li>
            </a>
            {# 给每个选项卡的a标签加上请求的路径与参数 #}
            <a href="{% url 'web:feedback' 'student-evaluation' %}">
                {# 判断一下:如果传过来的table值是当前的标签的值,就加上 thisli 的效果 #}
                <li class="{% if table == 'student-evaluation' %}thisli{% endif %}" back_type="2">
                    <img src="{% static 'oldboy/images/classmate-say/classmate-say-icon2.jpg' %}" alt="">
                    <img src="{% static 'oldboy/images/classmate-say/classmate-say-icon2-1.jpg' %}" alt="">
                    <span>学员评价</span>
                </li>
            </a>
            {# 给每个选项卡的a标签加上请求的路径与参数 #}
            <a href="{% url 'web:feedback' 'work-invitation' %}">
                {# 判断一下:如果传过来的table值是当前的标签的值,就加上 thisli 的效果 #}
                <li class="{% if table == 'work-invitation' %}thisli{% endif %}" back_type="3">
                    <img src="{% static 'oldboy/images/classmate-say/classmate-say-icon3.jpg' %}" alt="">
                    <img src="{% static 'oldboy/images/classmate-say/classmate-say-icon3-1.jpg' %}" alt="">
                    <span>提醒</span>
                </li>
            </a>
            <a href="">
                <li>
                    <img src="{% static 'oldboy/images/classmate-say/classmate-say-icon4.jpg' %}" alt="">
                    <img src="{% static 'oldboy/images/classmate-say/classmate-say-icon4-1.jpg' %}" alt="">
                    <span>同学说 <i>(99+)</i></span>
                </li>
            </a>
            <a href="">
                <li>
                    <img src="{% static 'oldboy/images/classmate-say/classmate-say-icon5.jpg' %}" alt="">
                    <img src="{% static 'oldboy/images/classmate-say/classmate-say-icon5-1.jpg' %}" alt="">
                    <span>专访</span>
                </li>
            </a>
        </ul>
        <div id="fh5co-main">
            <div class="container">
                <div class="row">
                    <div id="fh5co-board" data-columns>

                        {# 这是图片展示写死的部分~~仅用于测试 #}
{#                        <div class="item">#}
{#                            <div class="animate-box">#}
{#                                <a href="{% get_media_prefix %}img/feedback/img_1.jpg"#}
{#                                   class="image-popup fh5co-board-img"><img#}
{#                                        src="{% get_media_prefix %}img/feedback/img_1.jpg"#}
{#                                        alt="Free HTML5 Bootstrap template"></a>#}
{#                            </div>#}
{#                        </div>#}
{#                        <div class="item">#}
{#                            <div class="animate-box">#}
{#                                <a href="{% get_media_prefix %}img/feedback/img_1.jpg"#}
{#                                   class="image-popup fh5co-board-img"><img#}
{#                                        src="{% get_media_prefix %}img/feedback/img_1.jpg"#}
{#                                        alt="Free HTML5 Bootstrap template"></a>#}
{#                            </div>#}
{#                        </div>#}

                    </div>
                </div>
            </div>
        </div>
    </div>
{% endblock %}


{% block js %}
    <!-- 滚动监听插件 -->
    <script src="{% static 'oldboy/plugins/jquery.waypoints.min.js' %}"></script>
    <!-- 点击图片放大js -->
    <script src="{% static 'oldboy/plugins/jquery.magnific-popup.min.js' %}"></script>
    <!-- 瀑布流自适应 -->
    <script src="{% static 'oldboy/plugins/salvattore.min.js' %}"></script>
    <!-- 瀑布流js -->
    <script src="{% static 'oldboy/plugins/main.js' %}"></script>
     <!-- 首页动效 实现瀑布流的代码 -->
    <script src="{% static 'classmate-say/learning-notes.js' %}"></script>

{% endblock %}

瀑布流的js代码主要在learning-nites.js中

里面的代码如下:

$(function () {
    var back_type = $('.thisli').attr('back_type');

    var page = 1;

    var num = 0;

    var next = 1;

    var tag = 1;

    function get_info() {

        if (next && tag) {
            tag = 0;
            // 发送ajax请求~~
            $.ajax({
//请求的路径加上参数~用ES6语法,可以加变量 url: `
/web/ajax_feedback/?back_type=${back_type}&page=${page}`, success: function (data) { // console.log(data) var results = data.results; next = data.next; for (var i in results) { var row = results[i]; var col = $('.column')[num % 4]; var item = ` <div class="item"> <div class="animate-box"> <a href="${row.img}" class="image-popup fh5co-board-img"><img src="${row.img}" alt="Free HTML5 Bootstrap template"></a> </div> </div>`; $(col).append(item); // 调用main.js中的两个函数!!! magnifPopup(); animateBoxWayPoint(); num += 1 } page += 1; tag = 1; } }) } } get_info(); //图片分批加载 $(window).scroll(function () { //$(document).scrollTop() 滚动条位置距页面顶部的距离; //$(document).height() 整个页面的总高度; //$(window).height() 当前窗口的高度; //判断是否已经滚动到页面底部; if ($(document).scrollTop() >= $(document).height() - $(window).height() - 180) { get_info(); } // alert(1111) }); }());

main.js的内容如下

由于实现瀑布流的代码中用到了main.js的两个函数,这里也把main.js的内容发一下:

// Magnific Popup
var magnifPopup = function () {
    $('.image-popup').magnificPopup({
        type: 'image',
        removalDelay: 300,
        mainClass: 'mfp-with-zoom',
        titleSrc: 'title',
        gallery: {
            enabled: true
        },
        zoom: {
            enabled: true, // By default it's false, so don't forget to enable it
            duration: 300, // duration of the effect, in milliseconds
            easing: 'ease-in-out', // CSS transition easing function
            // The "opener" function should return the element from which popup will be zoomed in
            // and to which popup will be scaled down
            // By defailt it looks for an image tag:
            opener: function (openerElement) {
                // openerElement is the element on which popup was initialized, in this case its <a> tag
                // you don't need to add "opener" option if this code matches your needs, it's defailt one.
                return openerElement.is('img') ? openerElement : openerElement.find('img');
            }
        }
    });
};

var animateBoxWayPoint = function () { if ($('.animate-box').length > 0) { $('.animate-box').waypoint(function (direction) { if (direction === 'down' && !$(this).hasClass('animated')) { $(this.element).stop().animate({ opacity: 1 }) } }, {offset: '75%'
}); } };
(function () {
'use strict'; // iPad and iPod detection var isiPad = function () { return (navigator.platform.indexOf("iPad") != -1); }; var isiPhone = function () { return ( (navigator.platform.indexOf("iPhone") != -1) || (navigator.platform.indexOf("iPod") != -1) ); }; // OffCanvass var offCanvass = function () { $('body').on('click', '.js-fh5co-menu-btn, .js-fh5co-offcanvass-close', function () { $('#fh5co-offcanvass').toggleClass('fh5co-awake'); }); }; // Click outside of offcanvass var mobileMenuOutsideClick = function () { $(document).click(function (e) { var container = $("#fh5co-offcanvass, .js-fh5co-menu-btn"); if (!container.is(e.target) && container.has(e.target).length === 0) { if ($('#fh5co-offcanvass').hasClass('fh5co-awake')) { $('#fh5co-offcanvass').removeClass('fh5co-awake'); } } }); $(window).scroll(function () { if ($(window).scrollTop() > 500) { if ($('#fh5co-offcanvass').hasClass('fh5co-awake')) { $('#fh5co-offcanvass').removeClass('fh5co-awake'); } } }); }; $(function () { magnifPopup(); offCanvass(); mobileMenuOutsideClick(); animateBoxWayPoint(); }); }());

 

posted on 2019-07-24 21:45  江湖乄夜雨  阅读(395)  评论(0编辑  收藏  举报