将内容滑出/移出屏幕时会出现嵌套的CSS过渡问题

时间:2018-01-27 15:51:48

标签: jquery html css css3 css-transitions

我有一个2列布局,我想要实现的效果是当点击一个切换按钮时,左(窄)列动画离开屏幕。然后剩余的列扩展以填充剩余空间。

再次单击切换将基本上反转动画。内容返回原始大小,然后另一列向后滑动以填充它留下的空间。

我本质上有这个工作,但过渡导致一些问题。当我将try: import tkinter as tk except: import Tkinter as tk class Demo(tk.LabelFrame): """ A LabeFrame that in order to demonstrate the string returned by the get method of Text widget, selects the characters in between the given arguments that are set with Scales. """ def __init__(self, master, *args, **kwargs): tk.LabelFrame.__init__(self, master, *args, **kwargs) self.start_arg = '' self.end_arg = None self.position_frames = dict() self._create_widgets() self._layout() self.update() def _create_widgets(self): self._is_two_args = tk.Checkbutton(self, text="Use 2 positional arguments...") self.position_frames['start'] = PositionFrame(self, text="start='{}.{}'.format(line, column)") self.position_frames['end'] = PositionFrame( self, text="end='{}.{}'.format(line, column)") self.text = TextWithStats(self, wrap='none') self._widget_configs() def _widget_configs(self): self.text.update_callback = self.update self._is_two_args.var = tk.BooleanVar(self, value=False) self._is_two_args.config(variable=self._is_two_args.var, onvalue=True, offvalue=False) self._is_two_args['command'] = self._is_two_args_handle for _key in self.position_frames: self.position_frames[_key].line.slider['command'] = self.update self.position_frames[_key].column.slider['command'] = self.update def _layout(self): self._is_two_args.grid(sticky='nsw', row=0, column=1) self.position_frames['start'].grid(sticky='nsew', row=1, column=0) #self.position_frames['end'].grid(sticky='nsew', row=1, column=1) self.text.grid(sticky='nsew', row=2, column=0, rowspan=2, columnspan=2) _grid_size = self.grid_size() for _col in range(_grid_size[0]): self.grid_columnconfigure(_col, weight=1) for _row in range(_grid_size[1] - 1): self.grid_rowconfigure(_row + 1, weight=1) def _is_two_args_handle(self): self.update_arguments() if self._is_two_args.var.get(): self.position_frames['end'].grid(sticky='nsew', row=1, column=1) else: self.position_frames['end'].grid_remove() def update(self, event=None): """ Updates slider limits, argument values, labels representing the get method call. """ self.update_sliders() self.update_arguments() def update_sliders(self): """ Updates slider limits based on what's written in the text and which line is selected. """ self._update_line_sliders() self._update_column_sliders() def _update_line_sliders(self): if self.text.lines_length: for _key in self.position_frames: self.position_frames[_key].line.slider['state'] = 'normal' self.position_frames[_key].line.slider['from_'] = 1 _no_of_lines = self.text.line_count self.position_frames[_key].line.slider['to'] = _no_of_lines else: for _key in self.position_frames: self.position_frames[_key].line.slider['state'] = 'disabled' def _update_column_sliders(self): if self.text.lines_length: for _key in self.position_frames: self.position_frames[_key].column.slider['state'] = 'normal' self.position_frames[_key].column.slider['from_'] = 0 _line_no = int(self.position_frames[_key].line.slider.get())-1 _max_line_len = self.text.lines_length[_line_no] self.position_frames[_key].column.slider['to'] = _max_line_len else: for _key in self.position_frames: self.position_frames[_key].column.slider['state'] = 'disabled' def update_arguments(self): """ Updates the values representing the arguments passed to the get method, based on whether or not the 2nd positional argument is active and the slider positions. """ _start_line_no = self.position_frames['start'].line.slider.get() _start_col_no = self.position_frames['start'].column.slider.get() self.start_arg = "{}.{}".format(_start_line_no, _start_col_no) if self._is_two_args.var.get(): _end_line_no = self.position_frames['end'].line.slider.get() _end_col_no = self.position_frames['end'].column.slider.get() self.end_arg = "{}.{}".format(_end_line_no, _end_col_no) else: self.end_arg = None self._update_method_labels() self._select() def _update_method_labels(self): if self.end_arg: for _key in self.position_frames: _string = "text.get('{}', '{}')".format( self.start_arg, self.end_arg) self.position_frames[_key].label['text'] = _string else: _string = "text.get('{}')".format(self.start_arg) self.position_frames['start'].label['text'] = _string def _select(self): self.text.focus_set() self.text.tag_remove('sel', '1.0', 'end') self.text.tag_add('sel', self.start_arg, self.end_arg) if self.end_arg: self.text.mark_set('insert', self.end_arg) else: self.text.mark_set('insert', self.start_arg) class TextWithStats(tk.Text): """ Text widget that stores stats of its content: self.line_count: the total number of lines self.lines_length: the total number of characters per line self.update_callback: can be set as the reference to the callback to be called with each update """ def __init__(self, master, update_callback=None, *args, **kwargs): tk.Text.__init__(self, master, *args, **kwargs) self._events = ('<KeyPress>', '<KeyRelease>', '<ButtonRelease-1>', '<ButtonRelease-2>', '<ButtonRelease-3>', '<Delete>', '<<Cut>>', '<<Paste>>', '<<Undo>>', '<<Redo>>') self.line_count = None self.lines_length = list() self.update_callback = update_callback self.update_stats() self.bind_events_on_widget_to_callback( self._events, self, self.update_stats) @staticmethod def bind_events_on_widget_to_callback(events, widget, callback): """ Bind events on widget to callback. """ for _event in events: widget.bind(_event, callback) def update_stats(self, event=None): """ Update self.line_count, self.lines_length stats and call self.update_callback. """ _string = self.get('1.0', 'end-1c') _string_lines = _string.splitlines() self.line_count = len(_string_lines) del self.lines_length[:] for _line in _string_lines: self.lines_length.append(len(_line)) if self.update_callback: self.update_callback() class PositionFrame(tk.LabelFrame): """ A LabelFrame that has two LabelFrames which has Scales. """ def __init__(self, master, *args, **kwargs): tk.LabelFrame.__init__(self, master, *args, **kwargs) self._create_widgets() self._layout() def _create_widgets(self): self.line = SliderFrame(self, orient='vertical', text="line=") self.column = SliderFrame(self, orient='horizontal', text="column=") self.label = tk.Label(self, text="Label") def _layout(self): self.line.grid(sticky='ns', row=0, column=0, rowspan=2) self.column.grid(sticky='ew', row=0, column=1, columnspan=2) self.label.grid(sticky='nsew', row=1, column=1) self.grid_rowconfigure(1, weight=1) self.grid_columnconfigure(1, weight=1) class SliderFrame(tk.LabelFrame): """ A LabelFrame that encapsulates a Scale. """ def __init__(self, master, orient, *args, **kwargs): tk.LabelFrame.__init__(self, master, *args, **kwargs) self.slider = tk.Scale(self, orient=orient) self.slider.pack(fill='both', expand=True) if __name__ == '__main__': root = tk.Tk() demo = Demo(root, text="text.get(start, end=None)") with open(__file__) as f: demo.text.insert('1.0', f.read()) demo.text.update_stats() demo.pack(fill='both', expand=True) root.mainloop() 添加到窄列时,这会影响其中的孩子。这是一个CodePen:

https://codepen.io/moy/pen/zROvWN

我注意到的另一个问题是滚动条出现在浏览器窗口上,即使有足够的空间。我想这是因为它认为窄栏中的内容已被压扁,现在真的很高。我有什么想法可以避免这种情况并解决我遇到的问题吗?

编辑:也许值得注意的是,我在窄列中有一个包装器div的原因是transition-delay元素上的填充在设置转换时导致了问题。这就是为什么我没有该列的转换时间,但它已应用于其中的.grid__item div。

希望有人可以提供帮助!

1 个答案:

答案 0 :(得分:0)

我将时间从0.4s增加到1s,以便您可以轻松看到所需的结果,

如果我误解了您的要求,可以自由讨论, 正如我上面评论的那样 您要做的就是在两个元素上应用相同的持续时间,而无需延迟。

$(document).ready(function(){
	$(".filter-toggle").click(function(){
	    $(".grid").toggleClass("hide-filters");
	});
});
/* #MIXINS */
/* Body */
body {
  margin: 0 auto;
  padding: 30px 0 0;
  max-width: 1200px;
}

/* #GRID */
.grid {
  margin-left: -30px;
  display: -webkit-box;
  display: flex;
  overflow: hidden;
}
.grid:before, .grid:after {
  content: "";
  display: table;
}
.grid:after {
  clear: both;
}

.grid__item {
  box-sizing: border-box;
  padding-left: 30px;
  width: 100%;
}

.one-half,
.two-quarters {
  width: 50%;
}

.one-third {
  width: 33.333%;
}

.two-thirds {
  width: 66.666%;
}

.one-quarter {
  width: 25%;
}

.three-quarters {
  width: 75%;
}

/* #THE PROBLEM */
.filter-controls {
  margin-bottom: 30px;
}
.filter-controls .filter-toggle {
  background: red;
  display: inline-block;
  padding: 20px;
}

.filter-grid .filter-grid__filters {
  -webkit-transition: all 1s;
  transition: all 1s;
}
.filter-grid .filters {
  -webkit-transition: all 10s;
  transition: all 1s;
}
.filter-grid .filter-grid__content {
  -webkit-transition: width .40s;
  transition: width 1s;
  -webkit-transition-delay: 0;
          transition-delay: 0;
}

.hide-filters .filter-grid__filters {
  padding-left: 0;
  width: 0;
  overflow: hidden;
  -webkit-transform: translateX(-100%);
          transform: translateX(-100%);
}
.hide-filters .filter-grid__content {
  width: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
  <div class="filter-controls">
    <span class="btn filter-toggle">Toggle</span>
  </div>

  <div class="grid filter-grid">

    <div class="grid__item one-quarter filter-grid__filters">

      <div class="filters">
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
          dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
      </div>

    </div>

    <div class="grid__item three-quarters filter-grid__content">

      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
        dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

    </div>
</body>