Fix resizing in controls to work for all sizes including full screen

This commit is contained in:
Sam El-Husseini 2017-12-27 16:30:42 -08:00
parent 342e714ae2
commit 8be4bb11d8
5 changed files with 85 additions and 30 deletions

View File

@ -33,11 +33,18 @@ namespace pxsim.visuals {
font-family:"Lucida Console", Monaco, monospace;
font-size:8px;
fill:#fff;
pointer-events: none; user-select: none;
pointer-events: none;
user-select: none;
}
.sim-text.small {
font-size:6px;
}
.sim-text.large {
font-size:30px;
}
.sim-text.number {
font-family: Lato, Work Sans, PT Serif, Source Serif Pro;
}
.sim-text.inverted {
fill:#000;
}

View File

@ -5,6 +5,8 @@ namespace pxsim.visuals {
export const CONTROL_WIDTH = 87.5;
export const CONTROL_HEIGHT = 175;
export const CONTROL_TEXT_COLOR = '#000';
export abstract class ControlView<T extends BaseNode> extends SimView<T> implements LayoutElement {
protected content: SVGSVGElement;
@ -36,7 +38,7 @@ namespace pxsim.visuals {
}
buildDom(): SVGElement {
this.content = svg.elt("svg", { viewBox: `0 0 ${this.getInnerWidth()} ${this.getInnerHeight()}`}) as SVGSVGElement;
this.content = svg.elt("svg", { viewBox: `0 0 ${this.getInnerWidth()} ${this.getInnerHeight()}` }) as SVGSVGElement;
this.content.appendChild(this.getInnerView(this.parent, this.globalDefs));
return this.content;
}
@ -52,8 +54,18 @@ namespace pxsim.visuals {
const currentHeight = this.getInnerHeight();
const newHeight = currentHeight / currentWidth * width;
const newWidth = currentWidth / currentHeight * height;
if (newHeight > height) {
// scale width instead
this.content.setAttribute('width', `${newWidth}`);
this.content.setAttribute('height', `${height}`);
// translate to the middle (width)
this.translate(width / 2 - newWidth / 2, 0);
} else {
this.content.setAttribute('width', `${width}`);
this.content.setAttribute('height', `${newHeight}`);
// translate to the middle (height)
this.translate(0, height / 2 - newHeight / 2);
}
}
}

View File

@ -7,35 +7,46 @@ namespace pxsim.visuals {
getInnerView() {
this.group = svg.elt("g") as SVGGElement;
this.group.setAttribute("transform", `translate(17, ${20 + this.getHeight() / 4}) scale(5)`)
const innerHeight = 13;
const innerWidth = 11;
this.group.setAttribute("transform", `translate(1.02, 1.5) scale(0.8)`)
const colorIds = ['red', 'yellow', 'blue', 'green', 'black', 'grey'];
const colors = ['#f12a21', '#ffd01b', '#006db3', '#00934b', '#000', '#6c2d00'];
const colorIds = ['red', 'yellow', 'blue', 'green', undefined, 'grey'];
const colors = ['#f12a21', '#ffd01b', '#006db3', '#00934b', undefined, '#6c2d00'];
const colorValue = [5, 4, 2, 3, 1, 7];
let cy = -4;
for (let c = 0; c < colorIds.length; c++) {
const cx = c % 2 == 0 ? 2.2 : 8.2;
if (c % 2 == 0) cy += 5;
if (colorIds[c]) {
const circle = pxsim.svg.child(this.group, "circle", { 'class': 'sim-color-grid-circle', 'cx': cx, 'cy': cy, 'r': '2', 'style': `fill: ${colors[c]}` });
circle.addEventListener(pointerEvents.down, ev => {
this.setColor(colorValue[c]);
})
}
}
const whiteCircleWrapper = pxsim.svg.child(this.group, "g", { 'id': 'white-cirlce-wrapper' });
pxsim.svg.child(whiteCircleWrapper, "circle", { 'class': 'sim-color-grid-circle', 'cx': 2.2, 'cy': '16', 'r': '2', 'style': `fill: #fff` });
pxsim.svg.child(whiteCircleWrapper, "circle", { 'cx': 2.2, 'cy': '16', 'r': '2', 'style': `fill: none;stroke: #94989b;stroke-width: 0.5px` });
pxsim.svg.child(whiteCircleWrapper, "circle", { 'class': 'sim-color-grid-circle', 'cx': 2.2, 'cy': '11', 'r': '2', 'style': `fill: #fff` });
pxsim.svg.child(whiteCircleWrapper, "circle", { 'cx': 2.2, 'cy': '11', 'r': '2', 'style': `fill: none;stroke: #94989b;stroke-width: 0.1px` });
whiteCircleWrapper.addEventListener(pointerEvents.down, ev => {
this.setColor(6);
})
return this.group;
}
getInnerWidth() {
return 10.2;
}
getInnerHeight() {
return 15;
}
private setColor(color: number) {
const state = this.state;
state.setColor(color);
}
}
}

View File

@ -10,7 +10,7 @@ namespace pxsim.visuals {
getInnerView(parent: SVGSVGElement) {
this.defs = <SVGDefsElement>svg.child(this.element, "defs", {});
this.group = svg.elt("g") as SVGGElement;
this.group.setAttribute("transform", `translate(12, ${this.getHeight() / 2 - 15}) scale(2)`)
this.group.setAttribute("transform", `translate(12, 0) scale(2)`)
let gc = "gradient-color";
this.colorGradient = svg.linearGradient(this.defs, gc, true);
@ -53,6 +53,14 @@ namespace pxsim.visuals {
return this.group;
}
getInnerWidth() {
return CONTROL_WIDTH;
}
getInnerHeight() {
return CONTROL_WIDTH;
}
updateState() {
if (!this.visible) {
return;

View File

@ -7,7 +7,10 @@ namespace pxsim.visuals {
private gradient: SVGLinearGradientElement;
private slider: SVGGElement;
private static SLIDER_HANDLE_HEIGHT = 31;
private reporter: SVGTextElement;
private static SLIDER_HANDLE_HEIGHT = 26;
private static SLIDER_SIDE_PADDING = 6;
getInnerView(parent: SVGSVGElement, globalDefs: SVGDefsElement) {
let gid = "gradient-slider-" + this.getId();
@ -23,15 +26,19 @@ namespace pxsim.visuals {
this.group = svg.elt("g") as SVGGElement;
const sliderGroup = pxsim.svg.child(this.group, "g");
sliderGroup.setAttribute("transform", `translate(0, ${10 + this.getTopPadding()})`)
const reporterGroup = pxsim.svg.child(this.group, "g");
reporterGroup.setAttribute("transform", `translate(31, 42)`);
this.reporter = pxsim.svg.child(reporterGroup, "text", { 'x': 0, 'y': '0', 'class': 'sim-text number large inverted' }) as SVGTextElement;
const rect = pxsim.svg.child(sliderGroup, "rect", { 'x': this.getLeftPadding(), 'y': 2, 'width': this.getWidth() - this.getLeftPadding() * 2, 'height': this.getContentHeight(), 'style': `fill: url(#${gid})` });
const sliderGroup = pxsim.svg.child(this.group, "g");
sliderGroup.setAttribute("transform", `translate(${this.getWidth() / 2 - this.getSliderWidth() / 2}, ${this.getReporterHeight()})`)
const rect = pxsim.svg.child(sliderGroup, "rect", { 'x': DistanceSliderControl.SLIDER_SIDE_PADDING, 'y': 2, 'width': this.getSliderWidth() - DistanceSliderControl.SLIDER_SIDE_PADDING * 2, 'height': this.getSliderHeight(), 'style': `fill: url(#${gid})` });
this.slider = pxsim.svg.child(sliderGroup, "g", { "transform": "translate(0,0)" }) as SVGGElement;
const sliderInner = pxsim.svg.child(this.slider, "g");
pxsim.svg.child(sliderInner, "rect", { 'width': this.getWidth(), 'height': DistanceSliderControl.SLIDER_HANDLE_HEIGHT, 'rx': '2', 'ry': '2', 'style': 'fill: #f12a21' });
pxsim.svg.child(sliderInner, "rect", { 'x': '0.5', 'y': '0.5', 'width': this.getWidth() - 1, 'height': DistanceSliderControl.SLIDER_HANDLE_HEIGHT - 1, 'rx': '1.5', 'ry': '1.5', 'style': 'fill: none;stroke: #b32e29' });
pxsim.svg.child(sliderInner, "rect", { 'width': this.getSliderWidth(), 'height': DistanceSliderControl.SLIDER_HANDLE_HEIGHT, 'rx': '2', 'ry': '2', 'style': 'fill: #f12a21' });
pxsim.svg.child(sliderInner, "rect", { 'x': '0.5', 'y': '0.5', 'width': this.getSliderWidth() - 1, 'height': DistanceSliderControl.SLIDER_HANDLE_HEIGHT - 1, 'rx': '1.5', 'ry': '1.5', 'style': 'fill: none;stroke: #b32e29' });
const dragSurface = svg.child(this.group, "rect", {
x: 0,
@ -64,16 +71,24 @@ namespace pxsim.visuals {
return this.group;
}
private getLeftPadding() {
return this.getInnerWidth() * 0.12;
getInnerHeight() {
return 192;
}
private getTopPadding() {
return this.getInnerHeight() / 4;
getInnerWidth() {
return 111;
}
private getContentHeight() {
return this.getInnerHeight() * 0.6;
private getReporterHeight() {
return 50;
}
private getSliderHeight() {
return 110;
}
private getSliderWidth() {
return 62;
}
updateState() {
@ -82,15 +97,17 @@ namespace pxsim.visuals {
}
const node = this.state;
const percentage = node.getValue() / 10; /* convert back to cm */
const y = this.getContentHeight() * percentage / this.getMax();
const y = this.getSliderHeight() * percentage / this.getMax();
this.slider.setAttribute("transform", `translate(0, ${y - DistanceSliderControl.SLIDER_HANDLE_HEIGHT / 2})`);
// Update reporter text
this.reporter.textContent = `${parseFloat((percentage).toString()).toFixed(0)}`;
}
private updateSliderValue(pt: SVGPoint, parent: SVGSVGElement, ev: MouseEvent) {
let cur = svg.cursorPoint(pt, parent, ev);
const height = this.getContentHeight(); //DistanceSliderControl.SLIDER_HEIGHT;
const height = this.getSliderHeight();
const bBox = this.content.getBoundingClientRect();
let t = Math.max(0, Math.min(1, (this.getTopPadding() + height + bBox.top / this.scaleFactor - cur.y / this.scaleFactor) / height))
let t = Math.max(0, Math.min(1, (DistanceSliderControl.SLIDER_HANDLE_HEIGHT + height + bBox.top / this.scaleFactor - cur.y / this.scaleFactor) / height))
const state = this.state;
state.setDistance((1 - t) * (this.getMax()));