因为在Magento1上的一个项目激发了我写这篇博客。重要的信息或按钮操作悬浮在电商网站(PC网站和移动网站)中极为重要,他可以提高您的转换率。这篇博客着重讲解magento详细页中将添加购物的选项按钮悬浮在边栏。悬浮边栏的目的是是侧边栏元素始终在视窗口中显示(或者在满足某些条件时)。这是移动产品选项(magento可配置产品的下拉菜单,颜色,尺寸等),添加到购物车按钮或任何其他对您的产品很重要的元素的理想场所。也就是说,您的客户可以自由浏览产品上的所有内容,一旦决定购买产品,“添加到购物车”按钮就显示在眼前等着点击!

让我们开始在代码中进行更改以启用此功能。为了这篇博文的目的,我创建了一个自定义主题  Alwayly/StickySidebar

LESS代码

app/design/frontend/Alwayly/StickySidebar/web/css/source/里面创建_extend.less文件并复制/粘贴下面的代码:

.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
  .box-tocart .action.tocart {
    width: 100%;
    margin-right: 0;
  }
 
  .sidebar {
    &.fixed {
      position: fixed;
    }
  }
}

确保运行Grunt命令来创建符号链接并编译此代码(仅在PC上,它将侧边栏定位为固定元素,并使"添加到购物车"按钮占用全部宽度)。

XML代码

app/design/frontend/Alwayly/StickySidebar/Magento_Catalog/layout/ 中创建catalog_product_view.xml,然后复制/粘贴以下代码片段:

<page layout="2columns-right" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <referenceBlock remove="true" name="catalog.compare.sidebar" />
    <referenceBlock remove="true" name="wishlist_sidebar" />
 
    <move element="product.info" destination="sidebar.additional" />
 
    <referenceContainer name="sidebar.additional">
        <block class="Magento\Framework\View\Element\Template"
               name="sticky.sidebar.wrapper"
               template="Magento_Catalog::sticky-sidebar-js.phtml"
               after="-" />
    </referenceContainer>
</page>

这段代码负责以下内容:

  • 将页面布局从一列更改为右栏侧栏的两列
  • 删除使用此页面布局时包含的两个块(比较和愿望清单块)
  • 更改包含产品选项的块的位置并将其添加到侧边栏
  • 添加将用于调用AMD组件的模板文件,以处理悬浮边栏逻辑和计算

PHTML代码

app/design/frontend/Alwayly/StickySidebar/Magento_Catalog/templates/中创建sticky-sidebar-js.phtml并复制/粘贴以下代码片段:

<script type="text/javascript" data-mage-init='{"stickySidebar":{}}'></script>

RequireJS代码

app/design/frontend/Alwayly/StickySidebar/内部创建requirejs-config.js并复制/粘贴以下代码片段:

var config = {
    map: {
        "*": {
            stickySidebar: "js/sticky-sidebar",
        }
    }
};

jQuery代码

app/design/frontend/Alwayly/StickySidebar/web/js/sticky-sidebar.js中创建sticky-sidebar.js并粘贴以下代码片段:

define(["jquery", "matchMedia", "domReady!"], function ($, mediaCheck) {
    "use strict";
 
    var sidebar = {};
    var a2c = $(".product-add-form");
    var a2c_mobile_target = $(".product-info-main > .price-box");
    // nodes required to calculate sidebar params: width, left, padding-left
    var page_main = $(".page-main");
    var page_main_w;
    var main = $(".main");
    var main_w;
    // nodes required to calculate sidebar params: top
    var header = $(".page-header");
    var nav = $(".nav-sections");
    var breadcrumbs = $(".breadcrumbs");
    // luma specific css values
    var a2c_mb = parseInt($("#product-addtocart-button").css("margin-bottom"));
    var main_pb = parseInt(main.css("padding-bottom"));
    var tabs_mb = parseInt($(".product.info.detailed").css("margin-bottom"));
 
    sidebar.el = $(".sidebar");
    sidebar.padding_ratio = parseFloat(sidebar.el.css("padding-left")) / page_main.width();
    sidebar.updateHorizontalParams = function () {
        if (sidebar.el.hasClass("fixed")) {
            page_main_w = parseFloat(page_main.width());
            main_w = parseFloat(main.width());
 
            sidebar.width = page_main_w - main_w;
            sidebar.left = ($(window).width() - page_main_w) / 2 + main_w;
            sidebar.p_left = parseInt(page_main_w * sidebar.padding_ratio);
 
            sidebar.el.css({
                "width": sidebar.width + "px",
                "left": sidebar.left + "px",
                "padding-left": sidebar.p_left + "px"
            });
        }
    };
    sidebar.updateVerticalParams = function () {
        sidebar.height = sidebar.el.height();
 
        var scrolled_from_top = $(window).scrollTop();
        var header_h = header.outerHeight(true) || 0;
        var nav_h = nav.outerHeight(true) || 0;
        var breadcrumbs_h = breadcrumbs.outerHeight(true) || 0;
        var content_h = main.outerHeight(true) || 0;
        var sidebar_limit_top = header_h + nav_h + breadcrumbs_h;
        var sidebar_limit_bottom = sidebar_limit_top + content_h;
        var sidebar_limit_bottom_criteria = scrolled_from_top + sidebar.height + main_pb + a2c_mb - tabs_mb;
 
        if (sidebar_limit_bottom < sidebar_limit_bottom_criteria) {
            // sidebar should start drifting out of viewport on the top
            sidebar.top = sidebar_limit_bottom - sidebar_limit_bottom_criteria;
 
            sidebar.el.css({"top": sidebar.top + "px"});
        } else if (scrolled_from_top > sidebar_limit_top) {
            // header and breadcrumbs are now above viewport
            if (!sidebar.el.hasClass("fixed")) {
                sidebar.el.addClass("fixed");
                sidebar.updateHorizontalParams();
            }
            sidebar.top = 0;
 
            sidebar.el.css({"top": sidebar.top + "px"});
        } else {
            sidebar.el.removeClass("fixed").removeAttr("style");
        }
    };
 
    var onResize = function () {
        $(window).on("resize", function () {
            sidebar.updateHorizontalParams();
        });
    }, onScroll = function () {
        $(window).on("scroll", function () {
            sidebar.updateVerticalParams();
        });
    }, onInit = function () {
        mediaCheck({
            media: "(min-width: 768px)",
            entry: function () {
                sidebar.el
                    .addClass("fixed")
                    .prepend(a2c.detach());
 
                sidebar.updateHorizontalParams();
                sidebar.updateVerticalParams();
 
                onResize();
                onScroll();
            },
            exit: function () {
                a2c.detach().insertAfter(a2c_mobile_target);
 
                sidebar.el
                    .removeClass("fixed")
                    .removeAttr("style");
            }
        });
    };
 
    onInit();
});

下面我为您讲解代码的逻辑:

  • onInit()方法用于初始化逻辑
  • 通过使用matchMedia库,产品选项可以在移动和pc布局之间切换位置(这种元素的分离是必需的,因为在移动设备上,侧边栏将是页脚之前的最后一个元素,并且不会让页面到达页面的下方)。此媒体查询还负责添加(在PC上)或删除(在手机上)CSS类名“fixed
  • 当只在PC上时,JS会计算四个CSS属性(updateHorizo​​ntalParams() - > width,left,padding-left属性,updateVerticalParams() - > top属性)的值。并加载事件监听器(在页面调整大小和页面滚动进行相同的计算)
  • 侧栏的显示可以分为三种不同的状态:
    • 状态#1 - 只要面包屑在视口中可见,侧栏就会相对定位
    • 状态#2 - 一旦面包屑在视口外滚动,侧栏被定位为固定元素并将保持在视口中
      悬浮边栏 - 使边栏固定
    • 状态#3 - 一旦侧栏的底部与内容的底部对齐,侧栏开始在视口外滑动,就像页面的其余部分一样粘滞边栏 - 保持固定,但向上滚动

此代码已经过优化,可与Luma主题一起使用,因此您可能需要添加/清除此处所述的一些代码。