Redimensionar el lienzo
@artf y @shlomoko, iré explicando el paso poco a poco. Primero, necesito usar Jquery, pero puedes usar otra librería o integrarte dentro del motor GrapesJS. En mi caso quería que fuera transparente al motor. 1) Tengo dos elementos de div ocultos en el HTML del índice principal fuera del iframe que GrapesJS genera en t...
Lee la respuesta completa abajo ↓Pregunta
¿Hay alguna forma de que el lienzo redimensione de forma dinámica? es decir, no usar el Administrador de dispositivos, sino arrastrar y soltar el ancho, similar a lo que puedes hacer con paneles o componentes?
Gracias
Respuestas (3)
@artf y @shlomoko, iré explicando el paso poco a poco. Primero, necesito usar Jquery, pero puedes usar otra librería o integrarte dentro del motor GrapesJS. En mi caso quería que fuera transparente al motor.
- Tengo dos elementos de div ocultos en el HTML del índice principal fuera del iframe que GrapesJS genera en tiempo de ejecución:
<!-- CONSEJOS DE RESOLUCIÓN DEL DISPOSITIVO-->
<div class="device-resolution hidden">
<div class="dr-type">Phone - Paisaje</div>
<div class="dr-measure">Afecta a 767px y inferiores"</div>
</div>
<div class="iframe-handle-contenedor oculto">
<div class="handle right-handle">
<div class="canaleta-manilla"></div>
<div class="tab-handle"></div>
<div class="dim-indicator"></div>
<div class="js-mobile-list mobile-wrapper">
.....
</div>
</div>
<div class="handle left-handle"></div>
</div>
- El primer div llamado "device-resolution" mostrará la resolución del dispositivo compatible con este tamaño de pantalla.
- La segunda div contiene: -- La cuneta -- La barra vertical izquierda y derecha que envuelve el cuerpo cuando se presiona la canaleta
El siguiente fragmento de código es la hoja de estilos utilizada:
/* VOLVIENDO A HACER SONIDO DE SONIDO */
.iframe-handle-container .handle {
posición: absoluta;
arriba: 0;
abajo: 0;
índice z: 14;
}
.iframe-handle-container .handle:before {
contenido: "";
posición: absoluta;
arriba: 0;
izquierda: -3px;
ancho: 4px;
altura: 100%;
Antecedentes: #178df7;
pantalla: ninguna;
}
.iframe-handle-container .right-handle {
izquierda: -1px;
ancho: 14px;
}
.iframe-handle-container .left-handle {
izquierda: -1px;
ancho: 3px;
Eventos de puntería: todos;
cursor: redimensionamiento de col;
}
.iframe-handle-container .tab-handle {
posición: absoluta;
arriba: 50%;
ancho: 14px;
altura: 38px;
Margen arriba: -19px;
antecedentes: #808080;
cursor: redimensionamiento de col;
Eventos de puntería: todos;
Radio de borde superior derecho: 3px;
Radio de borde inferior derecho: 3px;
}
.iframe-handle-container .tab-handle:before,
.iframe-handle-container .tab-handle:after {
contenido: "";
posición: absoluta;
arriba: 8px;
abajo: 8 px;
ancho: 1px;
Antecedentes: #a6a6a6;
}
.iframe-handle-container .tab-handle:before {
izquierda: 5px;
}
.iframe-handle-container .tab-handle:after {
izquierda: 8px;
}
.iframe-handle-container .tab-handle:hover {
Antecedentes: #178df7;
}
.iframe-handle-container .tab-handle:hover:before,
.iframe-handle-container .tab-handle:hover:after {
Antecedentes: #48a5f9;
}
.iframe-handle-container .gutter-handle {
posición: absoluta;
arriba: 0;
izquierda: -3px;
ancho: 4px;
altura: 100%;
cursor: redimensionamiento de col;
Eventos de puntería: todos;
}
.iframe-handle-container:hover .handle:before {
pantalla: bloqueo;
}
.iframe-handle-container:pasa el cursor .tab-handle {
Antecedentes: #178df7;
color del borde: #178df7;
}
.iframe-handle-container:pasa el cursor .tab-handle:before,
.iframe-handle-container:pasa el cursor .tab-handle:after {
Antecedentes: #48a5f9;
}
.dim-indicator {
posición: absoluta;
arriba: 10%;
Altura: 24px;
margen izquierda: 22px;
Eventos de puntería: todos;
tamaño de fuente: 14px;
pantalla: ninguna;
relleno: 2px 9px;
Radio de frontera: 4px !importante;
color: #ffffff;
/* peso de fuente: negrita; */
ancho: 156px;
Color de fondo: RGB(0, 0, 0);
}
.mobile-wrapper{
posición: absoluta;
arriba: 15%;
margen-izquierda: -30px;
Eventos de puntería: todos;
color: #ffffff;
Ancho: 340px;
relleno: 14px;
}
.mobile-list li{
antecedentes: #808080;
Relleno: 3px;
Radio de frontera: 4px !importante;
margen inferior: 5px;
tipo de lista: ninguno;
relleno-izquierda: 11px;
}
- Cuando el usuario hace clic en un icono de pantalla de dispositivo, le muestro al manejador que redimensione el lienzo. --- Para ello, creé un método llamado "initDeviceEventHandle", que se encarga de inicializar el manejador de canalones, y otro método llamado "showDeviceResolution", que crea una copia clon de los dos DIVs que explicamos antes.
editor. Commands.add('set-device-tablet', {
run: function(editor, sender)
{
.....
},
stop: función stop(editor, sender) {
var device = deviceManager.get('Tablet High Resolution');
showDeviceResolution("tablet_portrait", dispositivo);
initDeviceEventHandle(dispositivo);
}
});
/**
* Esta función recibirá un tipo de pantalla y mostrará la descripción en el lado izquierdo del lienzo.
*
* @param tipo
* @param dispositivo
*/
var showDeviceResolution = function (type, device){
Nombre y descripción de la var;
var width = device.attributes.widthMedia;
Para reducir un poco el ancho y así poder mover el mango hasta este tamaño
var reduceWidth = width - maxReduceScreenPreviewSize;
$(".gjs-frame").width(reduceWidth);
interruptor (tipo) {
Caso "mobile_portrait":
nombre = "Teléfono - Retrato";
descripción = "Afecta - " + ancho + " y por debajo";
pausa;
Caso "mobile_landscape":
nombre = "Teléfono - Paisaje";
descripción = "Afecta - " + ancho +" y por debajo";
pausa;
Caso "tablet_portrait":
nombre = "Tableta - Retrato";
descripción = "Afecta - " + ancho +" y por debajo";
}
const deviceResolution = $(document).find(".gjs-cv-canvas").find(".device-resolution");
si (deviceResolution.length > 0){
deviceResolution.addClass("hidden");
deviceResolution.find(".dr-type").html(nombre);
deviceResolution.find(".dr-measure").html(descripción);
} else {
var copyDeviceResolution = $(document).find(".device-resolution").clone(true,true);
copyDeviceResolution.find(".dr-type").html(nombre);
copyDeviceResolution.find(".dr-measure").html(descripción);
$(document).find(".gjs-cv-canvas").prepend(copyDeviceResolution);
}
const glutterResize = $(document).find(".gjs-cv-canvas").find(".iframe-handle-container");
si (glutterResize.length > 0){
glutterResize.addClass("oculto");
} else {
Si el div aún no se ha creado dentro del iframe, entonces lo incluimos.
var copyGlutterResize = $(document).find(".iframe-handle-container").clone(true,true);
$(".gjs-frame").before(copyGlutterResize);
}
Obligamos a actualizar la pantalla porque entonces actualizaremos todas las dimensiones
setTimeout(función () {
$(ventana).trigger('redimensionar');
}, 600);
};
/**
* Esta función inicializa el control de gutters del dispositivo
*
*/
var initDeviceEventHandle = function (device) {
try {
var maxDeviceSize = parseInt(device.attributes.widthMedia,10);
Para reducir un poco el ancho y así poder mover el mango hasta este tamaño
var reduceWidth = maxDeviceSize - maxReduceScreenPreviewSize;
$(".gjs-frame").width(reduceWidth);
var widthIframe = 0; Ancho actual del iframe
var maxLeftPos = 0;
var finalwidth = 0;
$(".manilla-derecha").arrastrable({
Eje: "X",
start: function(event, ui) {
widthIframe = $(".gjs-frame").width();
},
arrastrar: función(evento, ui) {
try {
si ( $(".gjs-cv-canvas").find(".handle-mask").length == 0 ){
Necesitamos crear una máscara para evitar que en el momento en que arrastremos el puntero sobre el iframe y pierdas entonces el control del redimensionamiento.
$(".gjs-cv-canvas").append('<div class="handle-mask" style="position: absolute; z-index: 2; left: 0; top: 0; right: 0; bottom: 0;"></div>');
}
Necesitamos cambiar dinámicamente el ancho del iframe
const total = ui.posición.izquierda - ui.posiciónOriginal.izquierda;
ancho var = ancho Iframe + 2*total;
$('.js-lista-móvil').find(".móvil-item").addClass("hidden");
if(width > maxDeviceSize || width < minReduceScreenPreviewSize){
ui.position.left = maxLeftPos;
} else {
Establece el ancho del iframe
maxLeftPos = ui.position.left;
$(".gjs-frame").width(width);
ancho final = ancho;
Coloca la posición a la izquierda del mango izquierdo
var left = $(".gjs-frame")[0].offsetLeft;
$(".manilla-izquierda").css("izquierda", izquierda);
var leftDesc = left - 162; 162 = el ancho del panel derecho
$(".device-resolution").css("izquierda", izquierdaDesc);
$('.dim-indicator').html('Tamaño de pantalla' + ancho + 'px').fadeIn('lento');
}
Después de arrastrar, necesitamos refrescar el editor para recalcular el borde de resaltado en el elemento seleccionado.
editor.refresh();
} captura (err) {
consola.error(err);
}
},
stop: function(event, ui) {
try {
$(".handle-mask").remove();
} captura (err) {
consola.error(err);
}
}
});
} captura (err) {
consola.error(err);
}
};
- Este punto es importante porque cuando redimensionamos la pantalla también necesitamos controlar la canaleta. Así que en el método de "cargar" del editor, incluyo una nueva función para comprobar si el usuario está redimensionando el lienzo o el tamaño de la pantalla. Esto se llama "getWindowDims".
editor.on('load', function() {
Controla que el tamaño de la pantalla no sea demasiado pequeño
getWindowDims();
}
/**
* Función para determinar el tamaño del visor
*/
var getWindowDims = function() {
var doc = documento, w = ventana;
var docEl = (doc.compatMode & & doc.compatMode === 'CSS1Compat')?
doc.documentElement: doc.body;
var width = docEl.clientWidth;
var height = docEl.clientHeight;
¿Móvil ha hecho zoom?
si ( w.anchoInterno && ancho > w.AnchoInterno ) {
ancho = ancho interior (ancho interior);
altura = alturaInterior;
}
IMPORTANTE!!!
Información sobre el GutterHandle
var glutterHandleObj = $(document).find(".gjs-cv-canvas").find(".iframe-handle-container");
si (glutterHandleObj.length > 0){
var leftGlutterHandleBar = glutterHandleObj.find(".left-handle");
var rightGlutterHandleBar = glutterHandleObj.find(".right-handle");
var leftOffset = $('.gjs-frame')[0].offsetLeft;
var rightOffset = $('.gjs-frame')[0].offsetLeft + $('.gjs-frame').width();
leftGlutterHandleBar.css("cssText", "left: " + leftOffset + "px !important");
rightGlutterHandleBar.css("cssText", "left: " + rightOffset + "px !important");
glutterHandleObj.removeClass("hidden");
}
devolver {ancho: ancho, alto: alto};
};
Espero que esto te sea útil. No dudes en hacerme dudas. Enlace de la demo: http://recordit.co/RTEaUphDZ6
No @shlomoko, el lienzo no es redimensionable pero me encantaría ver un reparador permanente para eso (posiblemente con la misma lógica que se usa en los paneles).
Hola @artf, acabo de implementar una barra de lienzo para redimensionar, pero no sé si existe alguna forma de refrescar la posición de los bordes de los resaltos. Echa un vistazo al vídeo, por favor: http://recordit.co/jKlppYg2dD GJS-Badge GJS-toolbar Un saludo cordial.
Preguntas y respuestas relacionadas
Continúa investigando con debates sobre temas similares.
Issue #1791
Nombre del destino
@artf, ¿hay alguna forma de mostrar el nombre del elemento de destino? ! grapejs_drop
Issue #2419
[BUG] El modo de arrastre absoluto no funciona en dispositivos táctiles
El modo de arrastre absoluto (con el plugin touch de grapesjs) no funciona en dispositivos táctiles. GrapesJS versión: 0.15.8 Comportamient...
Issue #2592
Ancho modal
Hola, ¿hay alguna forma de establecer el ancho de un modal? Actualmente está configurado a 850px por CSS, pero me gustaría crear un diálogo...
Issue #1526
[PREGUNTA] cómo hacer un comando a pantalla completa
Hola, lamentablemente no encuentro documentación y no consigo entenderla por código: Sé que hay un comando incorporado 'pantalla completa',...
Plugins de pago que cumplen con este problema
Seleccionado por temas clave y relevancia de etiquetas para ayudarte a enviar más rápido.
Cargando recomendaciones de plugins de pago...
Consulta los plugins de código abierto de GrapesJS en GitHub O haz una búsqueda rápida en nuestro catálogo gratuito.
Explora plugins gratuitos →Los plugins premium incluyen soporte, actualizaciones regulares y funciones listas para producción — ahorrando días de trabajo de integración.
Explora plugins premium →Tutoriales relacionados
Guías detalladas sobre el mismo tema.
Tutorial
Super Tooltip for GrapesJS — Version 0.1.5 Released 🎉
We’re excited to announce the v 0.1.5 update of Super Tooltip, our floating‑menu and tooltip plugin for GrapesJS
Tutorial
GrapesJS in 2026: The Complete Guide to the Open-Source Web Builder Framework
Master GrapesJS in 2026. Architecture, code examples, React integration, plugin development, Studio SDK, and how it compares to other projects
Explorar categorías de plugins
Ve directamente a las páginas de categorías de plugins en el marketplace.