滑动面板,如何重现它们?

时间:2014-09-16 11:09:30

标签: javascript jquery html panel spotify

我可能在这里深水,我是JavaScript和jQuery的新手, 但我想尝试创建一个类似于spotify如何完成的面板系统。

看看这张照片:

Diag

在Spotify播放器网站上,当您点击艺术家或歌曲/专辑等内容时, 如果单击其他内容,它会在屏幕右侧的最顶部面板中滑动, 一个新的将出现在它的位置,前一个面板将添加到我称之为屏幕左侧的面板堆栈。

以下是Spotify的介绍: enter image description here

我想了解如何在JavaScript / jquery中执行此操作,是否有人可以分享一些输入?

我尝试了什么:(http://jsfiddle.net/k0Lh3ama/

我理解我的尝试很差,这就是我在这里

的原因
var idx = 0;
var panels = [];
var numpanels = 0;

function panel () {
    this.id = 0;
    this.active = false;
    this.container = {};
}

var panelmgr = new function () {
    this.Create = function (lpPanel) {

        //set all current panels to inactive 
        //and then push them left
        for (var i = 0; i < panels.length; i++) {
            panels[i].active = false;
            panels[i].container.css("left", "10%");
        }

        //set the newest panel to Active and Top Most
        lpPanel.container.css("z-index", 10000);
        lpPanel.container.css("left", "25%");

        //setup some info for the new panel
        lpPanel.id = numpanels++;
        lpPanel.active = true;

        //add it to array
        panels.push(lpPanel);
    };
}

$(".box").click(function (e) {            
    var id = $(this).attr("id");
    var selected = -1;

    //find the panel we've selected and retrieve the index
    for (var i = 0; i < panels.length; i++) {
        if (id == panels[i].container.attr("id")) {
            selected = I;
            break;
        }                    
    }

    //do we have a valid selected panel?
    if (selected >= 0) {

        //Make all panels not selected
        for (var i = 0; i < panels.length; i++) {
            panels[i].active = false;
            panels[i].container.css("left", "10%");
        }

        //now make the panel we selected 
        //the top most panel
        panels[selected].active = true;
        panels[selected].container.css("z-index", 10000);
        panels[selected].container.css("left", "25%");
    }



});

$(document).ready(function () {

    var p1 = new panel();
    var p2 = new panel();
    var p3 = new panel();
    var p4 = new panel();
    var p5 = new panel();

    p1.container = $("#panel1");
    p2.container = $("#panel2");
    p3.container = $("#panel3");
    p4.container = $("#panel4");
    p5.container = $("#panel5");

    panelmgr.Create(p1);
    panelmgr.Create(p2);
    panelmgr.Create(p3);
    panelmgr.Create(p4);
    panelmgr.Create(p5);
});

4 个答案:

答案 0 :(得分:2)

简而言之,您的原始代码存在一些问题。以下是我尝试使当前代码集正常工作(底部有改进建议。请参阅my original fiddle了解正常工作代码而不更改原始代码。我还修改了原始fiddle (with sliding)到使用css过渡来提供幻灯片效果)

1)你经常在你的面板上写字,因为他们的css top值被设置为零。您可以通过设置所有非活动面板的最高值来解决此问题。 (我以为你希望这个项目从堆栈中消失,因为你选择它时将它移到当前

//Increment height
var ii = 0;
for (var i = 0; i < panels.length; i++) {
    if(panels[i].active == false){
        panels[i].container.css("top", ii*30+"px");
        ii++;
    }
}

2)你的Z-index和宽度导致panel stack面板和current panel重叠,默认为最后创建的dom元素。

你可以通过在`// make all panels not selected``循环

中将z-index值设置为较低的值来解决这个问题。
panels[i].container.css("z-index", "1");

3)当你在堆栈中时,你可能还想隐藏current panels内容,否则你的堆栈会变得相当混乱。您可以通过将DOM面板分成以下内容来解决这个问题:

<div id="panel5" class="box">
    <div class="panelTitle">Panel 4</div>
    <div class="contents">Stuff to display</div>
</div>

并将以下代码添加到以下循环中:

//Make all panels not selected
for (var i = 0; i < panels.length; i++) {
    //other code emitted for space...
    //hide the contents
    panels[i].container.find(".contents").css("display","none");
}

//now make the panel we selected 
//the top most panel
panels[selected].active = true;
panels[selected].container.css("z-index", 2);
panels[selected].container.css("left", "25%");
panels[selected].container.css("top","0px");
//it's active, so display the contents
panels[selected].container.find(".contents").css("display","block");

4)如果您希望面板在点击上滑动,我添加了CSS过渡 - 仅在第二个小提琴中我向您的.box选择器添加了转换规则将对具有类box的元素的所有css更改进行第二次延迟。有关自定义转换的详情,请参阅css3 transitions

transition: all 1s;
-webkit-transition: all 1s;
-moz-transition: all 1s;
-o-transition: all 1s;

改善/改善发展的建议

说实话,我可能会进行大量重写。 DOM操作可以完成工作并且是一个公平的开始,但是如果事情变得复杂,那么在javascript中跟踪每个面板所需的数据会更加容易,并在需要时生成新鲜的DOM元素。我可能会按照以下免责声明的方式做一些事情,我没有测试以下代码作为一个整体,意味着作为指南

1)将包含所有相关信息的数据结构定义到面板并在javascript中实现。这与您已有的类似,但至少我要添加面板标题和面板内容排序。

与您的相似,但我会添加它并进行一些参数检查并删除容器

function Panel (jobj) {
    if(typeof jobj === "undefined") throw new ReferenceError("Bad value passed to constructor");
    if(typeof jobj.id === "undefined") throw new ReferenceError("Missing an id");
    this.id = 0;
    this.active = false;
    if(typeof jobj.title === "undefined") throw new ReferenceError("Missing panel title");
    this.title = jobj.title;
    //set to passed value, or if doesn't exist, default to empty array;
    this.tracks = jobj.tracks || [];
}

作为奖励,您可以利用原型设计并使用不同形式的参数检查构建不同类型的面板......我非常确定还有其他方法可以做到这一点,但我发现了以下为我工作。

var DiscoverPanel = function(jsonObj){
    if(typeof jsonObj === "undefined")throw new ReferenceError("Expecting a JSON object but received none");
    var panel = new Panel(jsonObj);
    if(typeof jsonObj.genre === "undefined") throw new ReferenceError("Missing genre!")
    panel.genre = jsonObj.genre;
    return panel;
}

2)为堆栈和当前面板创建HTML,因此,不要使用当前的5 div元素,而是将其缩小到2.不要忘记根据自己的喜好设计样式

<ul id="stack"></ul>
<div id="current"></div>

3)在javascript而不是html中定义面板。一旦你有传递给构造函数的底层json对象的工作示例,你可能会发现编写一个服务器端服务是有益的,你通过AJAX调用它返回必要的JSON。

构造函数将被调用如下:

//there are plenty of ways to generate the id within the constructor if hard coding
//it bugs you, your post showed a means of doing so.
var p1 = new Panel({title:"Panel 1",id:"p1"});
var p2 = new Panel({title:"Panel 2",id:"p2"});
var dp = new DiscoverPanel({title:"discover",id:"dp",genre:"rock"});
//etc.
var pn = new Panel({title:"Panel n"});
var panels = [p1,p2,dp,...,pn];

4)Onload / domready为非活动面板生成innerHTML,可能来自面板标题。

$(document).ready(function () {
    generateList();
}
function generateList(){
    var stack = document.getElementById("stack");
    stack.innerHTML = "";
    panels.forEach(function(panel){
        var item = document.createElement("li");
        item.setAttribute("id",panel.id)
        item.innerHTML = panel.title;
        item.onclick = function(){
            //load this specific panel to the current
            loadCurrent(panel);
            //regenerate the stack
            generateList();
        }
        stack.appendChild(item);
    });
}

5)继续为当前面板生成innerHTML。这与上述创建元素的方法非常相似,并且可以从面板的数据中生成元素。

function loadCurrent(panel){
    panel.active = true;
    var cur = document.getElementById("current");
    //Figured table was a good example, but you could get as creative as you want
    //using floats, divs, etc. Could also check the types and handle different types of panels
    var table = document.createElement("table");
    panel.tracks.forEach(function(track){
        var row = document.createElement("tr");
        var td = document.createElement("td");
        td.innerHTML = track.number;
        row.appendChild(td);
        //repeat for whatever other values you have for a track
        //you'd likely add a play function or something of that sort to each.
        table.appendChild(row);
    });
    table.appendChild(cur);
}

答案 1 :(得分:1)

选中fiddlehttp://jsfiddle.net/k0Lh3ama/1/

做css的东西。我不是主人..

你的CSS ::

.sidebar{
    width:10%;
    background-color:#000;
    color:#FFF;
    height:800px;
    float:left;

}
.box{
    width:7%;
    float:left;
    height:800px;
    background-color:red;
    border:1px solid #000;
}
.active{
    width:64%;
    float:right !important;
     -webkit-transition: all 1s ease-in-out;
-moz-transition: all 1s ease-in-out;
-o-transition: all 1s ease-in-out;
transition: all 1s ease-in-out;
}

您的Html代码     
     侧栏     

    <div id="panel2" class="box active">Panel 1 </div>

    <div id="panel3" class="box">Panel 2 </div>

    <div id="panel4" class="box">Panel 3</div>

    <div id="panel5" class="box">Panel 4 </div>

Jquery的

$(function(){
    $(".box").click(function(){
        $(".box").removeClass("active");
        $(this).addClass("active");
    }); 
});

答案 2 :(得分:1)

这并不是您正在寻找的内容,也与您发布的代码完全无关。但是,我把一些东西扔在一起,这可能是你看的好资源。它没有实现堆栈,但您可以非常轻松地应用这些概念。 Check it out

您可以摆脱createPanel函数并在init函数中预先创建/分配所有面板,然后让控制器使用这些面板作为基础。然后,它只是控制在DOM中显示的内容

display: none

会有效地从DOM中删除一个元素,并且可以用来隐藏某些面板。

答案 3 :(得分:0)

你可能不应该改变CSS。基本上,你想要的是两个div,一个包含&#34;面板列表&#34;并且可以详细查看单个&#34;面板&#34;。我认为这个问题分解为许多子问题:

1)从服务器获取面板对象列表,并动态填充左侧div,而不是使用包含面板信息的子div。换句话说,在页面加载时,需要运行一些代码,这些代码将循环遍历列表并将div添加到左侧div,每个面板一个,并且这些部分的CSS应该处理它们如何布局以及所有内容。一个简单的起点可能是为列表中的每个项目添加一个按钮,或单个图像等。

2)事件处理程序,这样当您单击列表中的面板时,它会将详细视图加载到右侧div中。这也可能会从列表中删除面板,或以某种方式(灰色显示)或其他任何方式更改它。

3)代码,如果项目已加载到右侧div中,则显示详细信息;如果没有,则执行其他默认信息。

欺骗一点以简化所有这些的一种方法可能是让面板和详细视图成为预先构建的页面,并将它们加载到iframe等主页面中。