简体   繁体   English

jQuery:当子元素接近其父元素的右边缘时,将DIV移至左侧(自动滚动的类型)

[英]jQuery: Move a DIV to left when its child element comes close to right edge of its parent element (type of auto-scrolling)

I'm currently building a somewhat basic video timeline. 我目前正在建立一个基本的视频时间表。 On this timeline are various media assets of variable duration and the width of the DIVs representing the assets reflect the duration, with 1 second being measured as 35px. 在此时间轴上,有各种持续时间可变的媒体资产,代表资产的DIV的宽度反映了持续时间,以1秒为35px进行度量。 So, for example, a 5 second asset would take up 175px in width on the timeline. 因此,例如,5秒的资产在时间轴上的宽度为175px。

Because the timeline needs to be longer than the width of my usable space on the page, it needs to scroll horizontally. 因为时间轴需要长于页面上可用空间的宽度,所以它需要水平滚动。 Instead of using an ugly standard scrollbar, I'm using a jQuery plugin scrollbar, which requires that the full-width DIV of the timeline sits inside another DIV that is the width of the usable area of the page and acts as a frame, with the inner DIV being absolutely positioned. 我使用的是jQuery插件滚动条,而不是使用丑陋的标准滚动条,它要求时间轴的全宽DIV位于另一个DIV内,该DIV是页面可用区域的宽度,并充当框架,内部DIV绝对定位。 When you move the scrollbar left or right it changes the "left" value of the inner DIV. 向左或向右移动滚动条时,它会更改内部DIV的“左”值。

Having given that context, I now come to my problem. 考虑到这种情况,我现在要解决我的问题。 The assets on the timeline need be horizontally resizable to adjust their duration. 时间轴上的资产需要水平调整大小以调整其持续时间。 I have that working using jQuery UI, but I need to make it so that when I drag the right edge of an asset near to the right edge of the outer DIV framing the timeline, the inner DIV of the timeline moves (basically scrolls) left and the width of the asset increases by 1 second (35px). 我已经使用jQuery UI进行了工作,但是我需要做到这一点,以便当我将资产的右边缘拖到框架时间轴的外部DIV的右边缘附近时,时间轴的内部DIV会向左移动(基本上滚动)资产的宽度增加1秒(35像素)。

Even this last bit I have working to a certain degree, but not well enough. 即使是最后一点,我也在一定程度上进行了工作,但还不够好。 What I need is that when I drag far enough to the right, so that I'm within 35-70 pixels of the right edge of the framing DIV, the inner DIV timeline will move to the left, the width of the asset will increase, and this will keep happening until I move my mouse back towards the left. 我需要的是,当我向右拖动足够远时,以便位于框架DIV右边缘的35-70像素之内,内部DIV时间线将向左移动,资产的宽度将增加,直到我将鼠标移回左侧之前,这种情况都会一直发生。

The best example I can think of is like when you're selecting text in your browser and you drag past the bottom of the screen, the screen starts scrolling down and it keeps doing that till you move your mouse up. 我能想到的最好的例子是,当您在浏览器中选择文本并拖过屏幕底部时,屏幕开始向下滚动,并且一直保持这种状态,直到您向上移动鼠标为止。

Currently I'm trying to to this by drawing on the "resize" event of the jQuery UI resizable element, but the problem is that I can't get that continuous effect I was just talking about, I have to keep dragging my mouse further to the right rather than just keeping it still. 目前,我正在尝试通过使用jQuery UI resizable元素的“调整大小”事件来实现此目的,但是问题是我无法获得我刚才所说的那种连续效果,我必须继续拖动鼠标而不是保持静止不动。 And when I reach the right edge of the window I have to release the mouse button, move back over to the resizing handle and start dragging again. 当我到达窗口的右边缘时,我必须释放鼠标按钮,移回调整大小手柄并再次开始拖动。

Here's the function I was trying to write (FYI, a .mediaInstance is an asset on the timeline): 这是我尝试编写的函数(仅供参考,.mediaInstance是时间轴上的资产):

//Scroll Timeline when resized handle comes close to right edge
        function timelineScroll() {

            //console.log('running');
            var mediaElement = $('#mediaTrack .mediaInstance.resizing');
            var track = $('#horiz_container_inner');

            //Determine location of right edge of the timeline viewport
            var timeline = $('#horiz_container_outer');
            var timelineOffset = timeline.offset();
            var timelineLeft = timelineOffset.left;

            var timelineRight = timelineLeft + $('#horiz_container_outer').width();

            //Find right edge of current .mediaInstance
            var instanceOffset = mediaElement.offset();
            var instanceLeft = instanceOffset.left;

            var instanceRight = instanceLeft + mediaElement.width();

            if ( (timelineRight-instanceRight) < 35 ) {

                var timelineCurrentLeft = Number(track.css('left').replace('px',''));
                var timelineNewLeft = timelineCurrentLeft - 70;
                track.css('left',timelineNewLeft);

                mediaCurrentWidth = mediaElement.width();
                mediaElement.width(mediaCurrentWidth+35);


                if (currentMousePos.x > timelineRight) {

                    while (currentMousePos.x > timelineRight) {

                        var timelineCurrentLeft = Number(track.css('left').replace('px',''));
                        var timelineNewLeft = timelineCurrentLeft - 35;
                        track.css('left',timelineNewLeft);

                        mediaCurrentWidth = mediaElement.width();
                        mediaElement.width(mediaCurrentWidth+35);

                    }

                }

            }

        }

You'll notice I even tried a loop at the end there based on the mouse position being farther right than the right edge of the framing DIV, but I didn't think it would work, and it didn't ... just seemed to put me in an infinite loop. 您可能会注意到,我甚至在最后尝试了一个循环,其原因是鼠标的位置比取景DIV的右边缘更右,但是我认为它不起作用,而且也没有...只是看起来使我陷入无限循环。

In any case, I'd really appreciate any help anyone can offer on this. 无论如何,我非常感谢任何人在此方面提供的任何帮助。 I'm working on a project with a really short turnaround time and I've never really done any of this particular stuff before. 我正在一个周转时间很短的项目上工作,而我之前从未真正做过任何这些特别的事情。

It turns out I solved my own problem. 原来我解决了自己的问题。 I just needed to use a setTimeout within the 'resize' function checking if the mouse was beyond the right edge of the framing DIV every 250 milliseconds and, if so, move the inner DIV left and increase the width of the asset. 我只需要在“调整大小”函数中使用setTimeout来检查鼠标是否每隔250毫秒超出框架DIV的右边缘,如果是,则将内部DIV左移并增加资产的宽度。 Here's what I used... 这是我用的...

EDIT : It turns out my solution didn't work as I'd hoped, so I could use some help after all. 编辑 :原来我的解决方案没有按我希望的那样工作,所以我毕竟可以使用一些帮助。

Here's the HTML: 这是HTML:

<div id="horiz_container_outer">
    <div id="horiz_container_inner" style="position: absolute; left: 0px; top: 0px; visibility: visible;">
        <div id="horiz_container" style="width: 10500px;">


            <div id="transitionTrack"></div>

            <div id="mediaTrack" class="ui-sortable ui-droppable">

                <div class="transitionBoxContainer first ui-droppable"></div>

                <div class="mediaInstance" assetid="001" assettype="video" thumb="video1_thumb.jpg" style="display: block; width: 419px;" type="asset" duration="12">
                    <div class="mediaThumbnail" style="background-image: url(./images/assets/thumbnails/video1_thumb.jpg);"></div>
                    <div class="mediaInfo">
                        <div class="mediaFilename">video1.avi</div>
                        <div class="mediaDuration">12s</div>
                        <div class="mediaHandle"></div>
                    </div>
                    <div class="transitionBoxContainer ui-droppable"></div>
                    <div class="deleteButton"></div>
                </div>

            </div><!-- End of #mediaTrack -->

        </div><!-- End of #horiz_container -->
    </div><!-- End of #horiz_container_inner -->
</div><!-- End of #horiz_container_outer -->

And here's my code to make the mediaInstance on the timeline resizable, snapping to 35px increments: 这是我的代码,可将时间轴上的mediaInstance调整为可调整大小,以35px为增量:

//Watch timeline assets for click on resize handle
$("#mediaTrack").on('mousedown','.mediaInstance .mediaHandle', function(e) {

    e.stopPropagation();
    e.preventDefault();


    //Find offset location of right edge of the timeline viewport
    var timelineViewport = $('#horiz_container_outer');
    var timelineViewportLeft = timelineViewport.offset().left;
    var timelineViewportRight = timelineViewportLeft + timelineViewport.width();

    //Assign track object to variable
    var track = $('#horiz_container_inner');

    var thisInstance = $(this).parents('.mediaInstance');

    //Store the mouse position before we start moving
    var startMousePos = e.pageX;


    $(document).mousemove(function(e){

        var currentInstanceWidth = thisInstance.width();

        //Find right edge offset of current .mediaInstance
        var instanceLeft = thisInstance.offset().left;
        var instanceRight = instanceLeft + currentInstanceWidth;


        if ( (e.pageX < (startMousePos-35)) || (e.pageX > (startMousePos+35)) ) {

            if ( e.pageX < (startMousePos-35) ) {

                thisInstance.width(currentInstanceWidth-35);

            } else { 

                                thisInstance.width(currentInstanceWidth+35);

            }

            startMousePos = e.pageX;
            recalcDuration(thisInstance);
            calcTotalDuration();

        }

    });

});
$(document).mouseup(function(e){
    $(document).unbind('mousemove');
});

That works great for the actual resizing, but the problem I'm having is that when I move the mouse past the right edge of #horiz_container_outer, which acts as a frame for the timeline, I want the #horiz_container_inner DIV to start moving its left position to the left by increments of 35px while also continuing to resize the .mediaInstance div to make it 35px wider ... and I want both those things to happen every 0.25 seconds ... HOWEVER, I don't want the "scrolling" of #horiz_container_inner to continuously fire with the mousemoves. 这对于实际调整大小非常有用,但是我遇到的问题是,当我将鼠标移过#horiz_container_outer的右边缘(充当时间轴的框架)时,我希望#horiz_container_inner DIV开始向左移动位置以35px的增量向左移动,同时还继续调整.mediaInstance div的大小以使其宽度增加35px ...而且我希望这两种情况每隔0.25秒发生一次...但是,我不希望“滚动” #horiz_container_inner的值可以随着鼠标移动而不断触发。 Once the mouse passes the right edge of #horiz_container_outer, I want some function to take over and start scrolling and resizing the .mediaInstance DIV at a set interval until the mouse once again moves left, past the right edge of #horiz_container_outer, at which point the original resizing shown above takes over again. 一旦鼠标经过#horiz_container_outer的右边缘,我希望某个函数接管并开始按设定的间隔滚动和调整.mediaInstance DIV的大小,直到鼠标再次向左移动,越过#horiz_container_outer的右边缘,此时上面显示的原始大小调整将再次接管。

The problem is that I have no idea how to achieve this. 问题是我不知道如何实现这一目标。 I tried using a flag variable and conditional to tell me when my mouse is "in the zone", with inTheZone = false to begin with, running a conditional to run my initial code only when inTheZone == false, then setting it to true once the mouse enters the right area and having a setTimeout takeover to loop the scrolling and resizing. 我尝试使用标志变量和条件告诉我鼠标何时位于“区域中”,首先使用inTheZone = false,仅当inTheZone == false时才运行条件以运行我的初始代码,然后将其设置为true鼠标进入右侧区域并进行setTimeout接管以循环滚动和调整大小。 This worked to a certain degree, but the mouse position suddenly became unavailable so I couldn't tell when I moved outside the zone and the div just kept scrolling indefinitely. 这在一定程度上有效,但是鼠标位置突然变得不可用,因此我无法分辨何时移动到区域之外,并且div一直无限滚动。

Any ideas? 有任何想法吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM