滚动容器中的半固定文本

时间:2015-06-15 20:33:33

标签: javascript html css knockout.js

我有一堆包含文字的水平框。这些盒子都在一个水平滚动的容器中:



link: function (scope, elem, attrs, ctrl) {
                var autocomplete;
var aaa=document.getElementById('address');

                function initializeGoogleMaps() {
                    autocomplete = new google.maps.places.Autocomplete(
                        (aaa), {
                            types: ['geocode']
                        });
                    scope.$on('$destroy', function () {
                        $(".pac-container").remove();
                        autocomplete=null;
                    });



    }

        initializeGoogleMaps();
// some other code

// generate some random data
var model = {
  leftEdge: ko.observable(0)
};
model.rows = populateArray(10 + randInt(20), randRow);

ko.applyBindings(model);

$(function() {
  $('.slide').on('scroll', function() {
    model.leftEdge(this.scrollLeft);
  })
})

function randRow() {
  var events = populateArray(50 + randInt(100), randEvent);
  var left = randInt(1000);
  events.forEach(function(event) {
    event.left = left;
    left += 10 + event.width + randInt(1000);
  });
  return {
    events: events
  }
}

function randEvent() {
  var word = randWord()
  var width = 50 + Math.max(8 * word.length, randInt(200));
  var event = {
    left: 0,
    width: width,
    label: word
  };
  event.offset = ko.computed(function() {
    // reposition the text to stay 
    // * within its container
    // * fully on-screen (if possible)
    var leftEdge = model.leftEdge();
    return Math.max(0, Math.min(
      leftEdge - event.left,
      event.width - 8 * event.label.length
    ));
  });
  return event;
}

function randWord() {
  var n = 2 + randInt(5);
  var ret = "";
  while (n-- > 0) {
    ret += randElt("rmhntsk");
    ret += randElt("aeiou");
  }
  return ret;
}

function randElt(arr) {
  return arr[randInt(arr.length)];
}

function populateArray(n, populate) {
  var arr = new Array(n);
  for (var i = 0; i < n; i++) {
    arr[i] = populate();
  }
  return arr;
}

function randInt(n) {
  return Math.floor(Math.random() * n);
}
&#13;
.slide {
  max-width: 100%;
  overflow: auto;
  border: 5px solid black;
}
.row {
  position: relative;
  height: 25px;
}
.event {
  position: absolute;
  top: 2.5px;
  border: 1px solid black;
  padding: 2px;
  background: #cdffff;
  font-size: 14px;
  font-family: monospace;
}
.event > span {
  position: relative;
}
&#13;
&#13;
&#13;

我想做的是当用户从左向右滚动时,重新定位每个框中与可见窗口的左边界部分重叠的文本,以使文本尽可能可见。 / p>

目前,我通过手动重新定位每个文字项目来做到这一点。

使用CSS有更清晰的方法吗?

1 个答案:

答案 0 :(得分:1)

一位朋友帮我提出了这个解决方案。

在英语中,我们的想法是为每个相对于滚动框框架而不是内容的行添加叠加层。

然后我们可以为在此叠加层中与左边缘重叠的任何框放置标签,当它下方的框滚动时,它将显示为平滑移动。

// generate some random data
var model = {
  leftEdge: ko.observable(0),
};
model.rows = populateArray(10 + randInt(20), randRow);
model.width = Math.max.apply(Math, $.map(model.rows, function(row) {
  return row.width
}));

ko.applyBindings(model);

$(function() {
  $('.slide').on('scroll', function() {
    model.leftEdge(this.scrollLeft);
  })
})

function randRow() {
  var events = populateArray(50 + randInt(100), randEvent);
  var left = randInt(1000);
  events.forEach(function(event) {
    event.left = left;
    left += 10 + event.width + randInt(1000);
  });
  return {
    events: events,
    width: left
  }
}

function randEvent() {
  var word = randWord()
  var width = 50 + Math.max(8 * word.length, randInt(200));
  var event = {
    width: width,
    label: word,
  };
  event.tense = ko.computed(function() {
    // reposition the text to stay#
    // * within its container
    // * fully on-screen (if possible)
    var leftEdge = model.leftEdge();
    return ['future', 'present', 'past'][
      (leftEdge >= event.left) + 
      (leftEdge > event.left + event.width - 8 * event.label.length)
    ];
  });
  return event;
}

function randWord() {
  var n = 2 + randInt(5);
  var ret = "";
  while (n-- > 0) {
    ret += randElt("rmhntsk");
    ret += randElt("aeiou");
  }
  return ret;
}

function randElt(arr) {
  return arr[randInt(arr.length)];
}

function populateArray(n, populate) {
  var arr = new Array(n);
  for (var i = 0; i < n; i++) {
    arr[i] = populate();
  }
  return arr;
}

function randInt(n) {
  return Math.floor(Math.random() * n);
}
.wrapper {
  position: relative;
  border: 5px solid black;
  font-size: 14px;
  font-family: monospace;
}
.slide {
  max-width: 100%;
  overflow: auto;
}
.slide > * {
  height: 25px;
}
.overlay {
  position: absolute;
  width: 100%;
  left: 0;
}
.overlay .past {
  display: none
}
.overlay .present {
  position: absolute;
  z-index: 1;
  top: 5.5px;
  left 0;
}
.overlay .future {
  display: none
}
.row {
  position: relative;
}
.event {
  position: absolute;
  top: 2.5px;
  border: 1px solid black;
  padding: 2px;
  background: #cdffff;
  height: 14px;
}
.event .past {
  float: right;
}
.event .present {
  display: none;
}
.event .future {
  float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div class="wrapper">
  <div class="slide" data-bind="foreach: rows, style: { width: width + 'px' }">
    <div class="overlay" data-bind="foreach: events">
      <span data-bind="text:label, css: tense"></span>
    </div>
    <div class="row" data-bind="foreach: events">
      <div class="event" data-bind="style: { left: left+'px', width: width+'px' }"><span data-bind="text:label, css: tense"></div>
    </div>
</div></div>

这不会导致 less javascript,但它确实会产生更高效的javascript,因为类更改的发生频率远低于偏移更改,因此需要更少的DOM元素更新。

您可以通过对水平空间进行一些预分区来处理每个“事件”(在上面的示例中),并且只更新相关分区中的事件。