#javascript #html #css #reactjs #flexbox
#javascript #HTML #css #reactjs #flexbox
Вопрос:
Я создаю компонент изменения размера с помощью ReactJS. Код ниже:
class Cell extends React.Component {
handleMouseDown = event => {
this.props.onMouseDown(this.props.index, event);
};
render() {
let verticalGrip = ( <
div onMouseDown = {
this.handleMouseDown
}
className = "cell-vertical-grip" / >
);
return ( <
div className = "cell-container"
style = {
{
width: this.props.widths[this.props.index]
}
} >
<
div className = "cell-content"
style = {
{
border: "10px solid transparent"
}
} >
{
"WIDTH " this.props.widths[this.props.index]
} <
/div> {
verticalGrip
} <
/div>
);
}
}
class Test extends React.Component {
state = {
widths: [100, 100, 100, 100],
baseWidths: [100, 100, 100, 100],
xBase: 0,
resizeIndex: null
};
handleMouseDown = (index, event) => {
console.log("MouseDown: index: " index ", pageX: " event.pageX);
this.setState({
xBase: event.pageX,
resizing: true,
resizeIndex: index
});
};
handleMouseMove = event => {
if (this.state.resizing) {
let delta = this.state.xBase - event.pageX;
console.log("MouseMove " delta);
let widths = this.state.widths.slice();
widths[this.state.resizeIndex] = this.state.baseWidths[this.state.resizeIndex] - delta;
this.setState({
widths: widths
});
}
};
handleMouseUp = event => {
console.log("MouseUp");
this.setState({
resizing: false,
resizeIndex: null
});
};
render() {
return ( <
div className = "test-container"
onMouseMove = {
this.handleMouseMove
}
onMouseUp = {
this.handleMouseUp
} >
<
Cell widths = {
this.state.widths
}
onMouseDown = {
this.handleMouseDown
}
index = {
0
}
/> <
Cell widths = {
this.state.widths
}
onMouseDown = {
this.handleMouseDown
}
index = {
1
}
/> <
Cell widths = {
this.state.widths
}
onMouseDown = {
this.handleMouseDown
}
index = {
2
}
/> <
Cell widths = {
this.state.widths
}
onMouseDown = {
this.handleMouseDown
}
index = {
3
}
/> <
/div>
);
}
}
// Render it
ReactDOM.render( <
Test / > ,
document.body
);
.test-container {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: row;
background-color: cyan;
}
.cell-container {
width: 100%;
height: 100px;
display: flex;
flex-direction: row;
background-color: grey;
border: 1px solid black;
overflow-y: hidden;
overflow-x: hidden;
}
.cell-content {
align-self: center;
flex-shrink: 1;
font-size: 12px;
overflow-y: hidden;
overflow-x: hidden;
background-color: white;
}
.cell-vertical-grip {
flex-shrink: 0;
margin-left: auto;
width: 3px;
min-width: 3px;
cursor: ew-resize;
background-color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
verticalGrip
Это место, где вы берете столбец для изменения размера.
Все в порядке, но моя проблема возникает, когда я изменяю размер любого столбца на ширину меньше 20px
. В этой ситуации моя синяя ручка ( verticalGrip
элемент) просто исчезает. Итак, если я отпущу мышь в этой позиции, я не смогу снова развернуть столбец, поскольку нет захвата для захвата (он исчез).
Другими словами, если ему по какой-то причине нужно уменьшить столбец, он не может увеличить его снова, поскольку нет захвата для захвата.
Как я могу сохранить видимость своего захвата на любой возможной ширине, позволяя пользователю изменять размер столбца при любых обстоятельствах?
Комментарии:
1. это из-за границы размером 10 пикселей, которую вы добавляете к элементу (2x10px = 20px)
Ответ №1:
Одна из идей состоит в том, чтобы сделать ваш элемент липким справа, и он не исчезнет при переполнении из-за границы, которую вы применяете к своему элементу.
class Cell extends React.Component {
handleMouseDown = event => {
this.props.onMouseDown(this.props.index, event);
};
render() {
let verticalGrip = ( <
div onMouseDown = {
this.handleMouseDown
}
className = "cell-vertical-grip" / >
);
return ( <
div className = "cell-container"
style = {
{
width: this.props.widths[this.props.index]
}
} >
<
div className = "cell-content"
style = {
{
border: "10px solid transparent"
}
} >
{
"WIDTH " this.props.widths[this.props.index]
} <
/div> {
verticalGrip
} <
/div>
);
}
}
class Test extends React.Component {
state = {
widths: [100, 100, 100, 100],
baseWidths: [100, 100, 100, 100],
xBase: 0,
resizeIndex: null
};
handleMouseDown = (index, event) => {
console.log("MouseDown: index: " index ", pageX: " event.pageX);
this.setState({
xBase: event.pageX,
resizing: true,
resizeIndex: index
});
};
handleMouseMove = event => {
if (this.state.resizing) {
let delta = this.state.xBase - event.pageX;
console.log("MouseMove " delta);
let widths = this.state.widths.slice();
widths[this.state.resizeIndex] = this.state.baseWidths[this.state.resizeIndex] - delta;
this.setState({
widths: widths
});
}
};
handleMouseUp = event => {
console.log("MouseUp");
this.setState({
resizing: false,
resizeIndex: null
});
};
render() {
return ( <
div className = "test-container"
onMouseMove = {
this.handleMouseMove
}
onMouseUp = {
this.handleMouseUp
} >
<
Cell widths = {
this.state.widths
}
onMouseDown = {
this.handleMouseDown
}
index = {
0
}
/> <
Cell widths = {
this.state.widths
}
onMouseDown = {
this.handleMouseDown
}
index = {
1
}
/> <
Cell widths = {
this.state.widths
}
onMouseDown = {
this.handleMouseDown
}
index = {
2
}
/> <
Cell widths = {
this.state.widths
}
onMouseDown = {
this.handleMouseDown
}
index = {
3
}
/> <
/div>
);
}
}
// Render it
ReactDOM.render( <
Test / > ,
document.body
);
.test-container {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: row;
background-color: cyan;
}
.cell-container {
width: 100%;
height: 100px;
display: flex;
flex-direction: row;
background-color: grey;
border: 1px solid black;
overflow-y: hidden;
overflow-x: hidden;
}
.cell-content {
align-self: center;
flex-shrink: 1;
font-size: 12px;
overflow-y: hidden;
overflow-x: hidden;
background-color: white;
}
.cell-vertical-grip {
flex-shrink: 0;
margin-left: auto;
width: 3px;
min-width: 3px;
cursor: ew-resize;
background-color: blue;
position:sticky;
right:0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Или вы можете рассмотреть другую идею вместо границы, такой как контур или прямоугольная тень, которая не повлияет на ширину элемента, и вы получите тот же визуальный результат:
class Cell extends React.Component {
handleMouseDown = event => {
this.props.onMouseDown(this.props.index, event);
};
render() {
let verticalGrip = ( <
div onMouseDown = {
this.handleMouseDown
}
className = "cell-vertical-grip" / >
);
return ( <
div className = "cell-container"
style = {
{
width: this.props.widths[this.props.index]
}
} >
<
div className = "cell-content"
style = {
{
outline: "10px solid #fff"
}
} >
{
"WIDTH " this.props.widths[this.props.index]
} <
/div> {
verticalGrip
} <
/div>
);
}
}
class Test extends React.Component {
state = {
widths: [100, 100, 100, 100],
baseWidths: [100, 100, 100, 100],
xBase: 0,
resizeIndex: null
};
handleMouseDown = (index, event) => {
console.log("MouseDown: index: " index ", pageX: " event.pageX);
this.setState({
xBase: event.pageX,
resizing: true,
resizeIndex: index
});
};
handleMouseMove = event => {
if (this.state.resizing) {
let delta = this.state.xBase - event.pageX;
console.log("MouseMove " delta);
let widths = this.state.widths.slice();
widths[this.state.resizeIndex] = this.state.baseWidths[this.state.resizeIndex] - delta;
this.setState({
widths: widths
});
}
};
handleMouseUp = event => {
console.log("MouseUp");
this.setState({
resizing: false,
resizeIndex: null
});
};
render() {
return ( <
div className = "test-container"
onMouseMove = {
this.handleMouseMove
}
onMouseUp = {
this.handleMouseUp
} >
<
Cell widths = {
this.state.widths
}
onMouseDown = {
this.handleMouseDown
}
index = {
0
}
/> <
Cell widths = {
this.state.widths
}
onMouseDown = {
this.handleMouseDown
}
index = {
1
}
/> <
Cell widths = {
this.state.widths
}
onMouseDown = {
this.handleMouseDown
}
index = {
2
}
/> <
Cell widths = {
this.state.widths
}
onMouseDown = {
this.handleMouseDown
}
index = {
3
}
/> <
/div>
);
}
}
// Render it
ReactDOM.render( <
Test / > ,
document.body
);
.test-container {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: row;
background-color: cyan;
}
.cell-container {
width: 100%;
height: 100px;
display: flex;
flex-direction: row;
background-color: grey;
border: 1px solid black;
overflow-y: hidden;
overflow-x: hidden;
}
/*to push the element so we can see the outline*/
.cell-container:before {
content:"";
width:10px;
}
.cell-content {
align-self: center;
flex-shrink: 1;
font-size: 12px;
overflow-y: hidden;
overflow-x: hidden;
background-color: white;
}
.cell-vertical-grip {
flex-shrink: 0;
margin-left: auto;
width: 3px;
min-width: 3px;
cursor: ew-resize;
background-color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Комментарии:
1. Спасибо.
position: sticky
спас мой день.2. @Mendes добавил другой способ 😉
Ответ №2:
Простым решением может быть небольшая доработка вашего CSS, чтобы ваши элементы захвата располагались с absolute
, выравнивались и имели размер по правому краю и высоте родительского элемента .cell-container
:
.cell-vertical-grip {
/* Add this */
position:absolute;
top:0;
height:100%;
right:0;
}
Вы также должны явно установить min-width
of .cell-container
в соответствии с шириной захвата, чтобы она все еще была видна, когда контейнер полностью свернут:
.cell-container {
/* Add this */
min-width:3px;
position:relative;
}
Я обновил ваш код с помощью этих изменений, которые работают во фрагменте ниже:
class Cell extends React.Component {
handleMouseDown = event => {
this.props.onMouseDown(this.props.index, event);
};
render() {
let verticalGrip = ( <
div onMouseDown = {
this.handleMouseDown
}
className = "cell-vertical-grip" / >
);
return ( <
div className = "cell-container"
style = {
{
width: this.props.widths[this.props.index]
}
} >
<
div className = "cell-content"
style = {
{
border: "10px solid transparent"
}
} >
{
"WIDTH " this.props.widths[this.props.index]
} <
/div> {
verticalGrip
} <
/div>
);
}
}
class Test extends React.Component {
state = {
widths: [100, 100, 100, 100],
baseWidths: [100, 100, 100, 100],
xBase: 0,
resizeIndex: null
};
handleMouseDown = (index, event) => {
console.log("MouseDown: index: " index ", pageX: " event.pageX);
this.setState({
xBase: event.pageX,
resizing: true,
resizeIndex: index
});
};
handleMouseMove = event => {
if (this.state.resizing) {
let delta = this.state.xBase - event.pageX;
console.log("MouseMove " delta);
let widths = this.state.widths.slice();
widths[this.state.resizeIndex] = this.state.baseWidths[this.state.resizeIndex] - delta;
this.setState({
widths: widths
});
}
};
handleMouseUp = event => {
console.log("MouseUp");
this.setState({
resizing: false,
resizeIndex: null
});
};
render() {
return ( <
div className = "test-container"
onMouseMove = {
this.handleMouseMove
}
onMouseUp = {
this.handleMouseUp
} >
<
Cell widths = {
this.state.widths
}
onMouseDown = {
this.handleMouseDown
}
index = {
0
}
/> <
Cell widths = {
this.state.widths
}
onMouseDown = {
this.handleMouseDown
}
index = {
1
}
/> <
Cell widths = {
this.state.widths
}
onMouseDown = {
this.handleMouseDown
}
index = {
2
}
/> <
Cell widths = {
this.state.widths
}
onMouseDown = {
this.handleMouseDown
}
index = {
3
}
/> <
/div>
);
}
}
// Render it
ReactDOM.render( <
Test / > ,
document.body
);
.test-container {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: row;
background-color: cyan;
}
.cell-container {
width: 100%;
height: 100px;
display: flex;
flex-direction: row;
background-color: grey;
border: 1px solid black;
overflow-y: hidden;
overflow-x: hidden;
/* Add this */
min-width:3px;
position:relative;
}
.cell-content {
align-self: center;
flex-shrink: 1;
font-size: 12px;
overflow-y: hidden;
overflow-x: hidden;
background-color: white;
}
.cell-vertical-grip {
flex-shrink: 0;
margin-left: auto;
width: 3px;
min-width: 3px;
cursor: ew-resize;
background-color: blue;
/* Add this */
position:absolute;
top:0;
height:100%;
right:0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>