Trung tâm một cửa sổ bật lên trên màn hình?


280

Làm cách nào chúng ta có thể căn giữa một cửa sổ bật lên được mở thông qua window.openchức năng javascript ở giữa biến màn hình với độ phân giải màn hình hiện được chọn?

Câu trả lời:


458

CHỨC NĂNG GIÁM SÁT / DUAL MONITOR (ghi có vào http://www.xtf.dk - cảm ơn bạn!)

CẬP NHẬT: Nó cũng sẽ hoạt động trên các cửa sổ không được tối đa hóa chiều rộng và chiều cao của màn hình nhờ vào @Frost!

Nếu bạn đang ở trên màn hình kép, cửa sổ sẽ nằm ở giữa, nhưng không theo chiều dọc ... hãy sử dụng chức năng này để tính đến điều đó.

const popupCenter = ({url, title, w, h}) => {
    // Fixes dual-screen position                             Most browsers      Firefox
    const dualScreenLeft = window.screenLeft !==  undefined ? window.screenLeft : window.screenX;
    const dualScreenTop = window.screenTop !==  undefined   ? window.screenTop  : window.screenY;

    const width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
    const height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;

    const systemZoom = width / window.screen.availWidth;
    const left = (width - w) / 2 / systemZoom + dualScreenLeft
    const top = (height - h) / 2 / systemZoom + dualScreenTop
    const newWindow = window.open(url, title, 
      `
      scrollbars=yes,
      width=${w / systemZoom}, 
      height=${h / systemZoom}, 
      top=${top}, 
      left=${left}
      `
    )

    if (window.focus) newWindow.focus();
}

Ví dụ sử dụng:

popupCenter({url: 'http://www.xtf.dk', title: 'xtf', w: 900, h: 500});  

TÍN DỤNG ĐI ĐẾN: http://www.xtf.dk/2011/08/center-new-popup-window-even-on.html (Tôi muốn chỉ liên kết đến trang này nhưng chỉ trong trường hợp trang web này bị sập mã ở đây trên SO, chúc mừng!)


7
Sau khi chơi xung quanh, điều này không hoạt động tốt như tôi nghĩ. Câu trả lời đơn giản hơn, ngoại trừ hoạt động tốt hơn nhiều. Điều này chỉ hoạt động nếu trang khởi chạy được tối đa hóa.
Bart

8
Cảm ơn về khoản tín dụng, tôi đã thực hiện ví dụ của mình trên các cửa sổ được thu nhỏ ngay bây giờ: xtf.dk/2011/08/center-new-popup-window-even-on.html
Frost

10
Sử dụng các biến toàn cục (chiều rộng / chiều cao), ouch!
Ruben Stol

13
Câu hỏi ban đầu được đăng vào năm 2010, giải pháp ban đầu được đăng vào năm 2010. Nhận xét của tôi về giải pháp ban đầu về việc không hoạt động trên màn hình kép được đăng vào năm 2013, câu trả lời của tôi cho màn hình kép được đăng vào năm 2013. Nhận xét của bạn về màn hình ba trong năm 2015. Bây giờ bạn cần trả lời cho một giải pháp ba màn hình trong năm 2015. Với tốc độ này, chúng tôi sẽ có câu trả lời cho 5 màn hình vào năm 2020, 6 màn hình vào năm 2025, 7 màn hình vào năm 2030 ... hãy tiếp tục chu kỳ này!
Tony M

2
@TonyM Mình đã cập nhật câu trả lời. Có chu kỳ cần phải tiếp tục!
Zo có

329

hãy thử nó như thế này:

function popupwindow(url, title, w, h) {
  var left = (screen.width/2)-(w/2);
  var top = (screen.height/2)-(h/2);
  return window.open(url, title, 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width='+w+', height='+h+', top='+top+', left='+left);
} 

17
Chức năng này không hoạt động trên thiết lập màn hình kép. Tôi đã đăng một giải pháp màn hình đơn và kép bên dưới.
Tony M

1
Tôi muốn xác nhận điều này: var left = (screen. Thong / 2) - (w / 2); var top = (screen.height / 2) - (h / 2); Không phải nó sẽ trả về left = 0 và top = 0 ??? Giả sử w bằng với screen. Thong và h bằng với screen.height ... Tôi đúng hay sai ở đây?
mutanic

1
@mutanic w / h đề cập đến kích thước của cửa sổ bật lên, không phải màn hình.
Mahn

2
Không tập trung vào màn hình thứ hai của tôi (đó là LÊN từ màn hình chính). Trả lời cho màn hình kép cũng thất bại.
vsync

2
Điều này sẽ không hoạt động nếu bạn muốn đặt cửa sổ ở giữa trình duyệt, thay vì ở giữa màn hình (ví dụ: nếu người dùng có kích thước trình duyệt của họ thành một nửa kích thước). Để tập trung trong trình duyệt, thay thế màn hình. Băng thông & screen.height bằng window.innerWidth & window.innerHeight
Jonathon Blok

71

Do sự phức tạp của việc xác định trung tâm của màn hình hiện tại trong thiết lập nhiều màn hình, một tùy chọn dễ dàng hơn là đặt giữa cửa sổ bật lên trên cửa sổ cha. Đơn giản chỉ cần vượt qua cửa sổ cha như một tham số khác:

function popupWindow(url, title, win, w, h) {
    const y = win.top.outerHeight / 2 + win.top.screenY - ( h / 2);
    const x = win.top.outerWidth / 2 + win.top.screenX - ( w / 2);
    return win.open(url, title, `toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width=${w}, height=${h}, top=${y}, left=${x}`);
}

Thực hiện:

popupWindow('google.com', 'test', window, 200, 100);

Đây dường như là kỹ thuật được Facebook sử dụng cho cửa sổ bật lên trên nút chia sẻ.
Tim Tonomall

3
Điều này làm việc hoàn hảo cho tôi trên màn hình kép. Ngay cả khi di chuyển hoặc thay đổi kích thước cửa sổ, nó vẫn nói trung tâm của cửa sổ. Đây phải là câu trả lời được chấp nhận. Cảm ơn.
Oli B

2
Tôi đồng ý với @OliB - điều này hoạt động hoàn hảo và giải quyết vấn đề phát triển gần đây mà chúng tôi đã có! Nên là câu trả lời được chấp nhận cho năm 2019.
MrLewk

Thực hiện một sửa đổi để mở rộng khả năng của chức năng này ở đây . Nó bao gồm tùy chọn để đặt chiều rộng và chiều cao theo tỷ lệ phần trăm hoặc tỷ lệ. Bạn cũng có thể thay đổi các tùy chọn bằng một đối tượng (dễ quản lý hơn chuỗi)
SwiftNinjaPro


15

Nếu bạn muốn căn giữa nó vào khung hình mà bạn hiện đang ở, tôi khuyên bạn nên sử dụng chức năng này:

function popupwindow(url, title, w, h) {
    var y = window.outerHeight / 2 + window.screenY - ( h / 2)
    var x = window.outerWidth / 2 + window.screenX - ( w / 2)
    return window.open(url, title, 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width=' + w + ', height=' + h + ', top=' + y + ', left=' + x);
} 

Tương tự như câu trả lời của Crazy Tim, nhưng không sử dụng window.top. Bằng cách này, nó sẽ hoạt động ngay cả khi cửa sổ được nhúng trong iframe từ một tên miền khác.


13

Nó hoạt động rất tốt trong Firefox.
Chỉ cần thay đổi biến hàng đầu thành bất kỳ tên nào khác và thử lại

        var w = 200;
        var h = 200;
        var left = Number((screen.width/2)-(w/2));
        var tops = Number((screen.height/2)-(h/2));

window.open("templates/sales/index.php?go=new_sale", '', 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width='+w+', height='+h+', top='+tops+', left='+left);

6
Nó hoàn toàn không cần thiết phải làm Number(...).
gustavohenke

6

Đề xuất của tôi là sử dụng vị trí hàng đầu 33% hoặc 25% từ không gian còn lại,
chứ không phải 50% như các ví dụ khác được đăng ở đây,
chủ yếu là do tiêu đề cửa sổ ,
trông đẹp hơn và thoải mái hơn cho người dùng,

mã hoàn chỉnh:

    <script language="javascript" type="text/javascript">
        function OpenPopupCenter(pageURL, title, w, h) {
            var left = (screen.width - w) / 2;
            var top = (screen.height - h) / 4;  // for 25% - devide by 4  |  for 33% - devide by 3
            var targetWin = window.open(pageURL, title, 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);
        } 
    </script>
</head>
<body>
    <button onclick="OpenPopupCenter('http://www.google.com', 'TEST!?', 800, 600);">click on me</button>
</body>
</html>



kiểm tra dòng này:
var top = (screen.height - h) / 4; // cho 25% - chia cho 4 | cho 33% - chia cho 3


6

Facebook sử dụng thuật toán sau để định vị cửa sổ bật lên đăng nhập của họ:

function PopupCenter(url, title, w, h) {
  var userAgent = navigator.userAgent,
      mobile = function() {
        return /\b(iPhone|iP[ao]d)/.test(userAgent) ||
          /\b(iP[ao]d)/.test(userAgent) ||
          /Android/i.test(userAgent) ||
          /Mobile/i.test(userAgent);
      },
      screenX = typeof window.screenX != 'undefined' ? window.screenX : window.screenLeft,
      screenY = typeof window.screenY != 'undefined' ? window.screenY : window.screenTop,
      outerWidth = typeof window.outerWidth != 'undefined' ? window.outerWidth : document.documentElement.clientWidth,
      outerHeight = typeof window.outerHeight != 'undefined' ? window.outerHeight : document.documentElement.clientHeight - 22,
      targetWidth = mobile() ? null : w,
      targetHeight = mobile() ? null : h,
      V = screenX < 0 ? window.screen.width + screenX : screenX,
      left = parseInt(V + (outerWidth - targetWidth) / 2, 10),
      right = parseInt(screenY + (outerHeight - targetHeight) / 2.5, 10),
      features = [];
  if (targetWidth !== null) {
    features.push('width=' + targetWidth);
  }
  if (targetHeight !== null) {
    features.push('height=' + targetHeight);
  }
  features.push('left=' + left);
  features.push('top=' + right);
  features.push('scrollbars=1');

  var newWindow = window.open(url, title, features.join(','));

  if (window.focus) {
    newWindow.focus();
  }

  return newWindow;
}

4

Bạn có thể sử dụng css để làm điều đó, chỉ cần cung cấp các thuộc tính sau cho phần tử được đặt ở giữa cửa sổ bật lên

element{

position:fixed;
left: 50%;
top: 50%;
-ms-transform: translate(-50%,-50%);
-moz-transform:translate(-50%,-50%);
-webkit-transform: translate(-50%,-50%);
 transform: translate(-50%,-50%);

}

3

Đây là phiên bản thay thế của giải pháp đã nói ở trên ...

function openPopupCenter(url, title, w, h) {
  // Fixes dual-screen position
  // Most browsers use window.screenLeft
  // Firefox uses screen.left
  var dualScreenLeft = getFirstNumber(window.screenLeft, screen.left),
    dualScreenTop = getFirstNumber(window.screenTop, screen.top),
    width = getFirstNumber(window.innerWidth, document.documentElement.clientWidth, screen.width),
    height = getFirstNumber(window.innerHeight, document.documentElement.clientHeight, screen.height),
    left = ((width / 2) - (w / 2)) + dualScreenLeft,
    top = ((height / 2) - (h / 2)) + dualScreenTop,
    newWindow = window.open(url, title, getSpecs());

  // Puts focus on the newWindow
  if (window.focus) {
    newWindow.focus();
  }

  return newWindow;

  function getSpecs() {
    return 'scrollbars=yes, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left;
  }

  function getFirstNumber() {
    for(var i = 0, len = arguments.length; i < len; i++) {
      var value = arguments[i];

      if (typeof value === 'number') {
        return value;
      }
    }
  }
}

3

Phiên bản của tôi với ES6 JavaScript.
Hoạt động tốt trên Chrome và Chromium với thiết lập màn hình kép.

function openCenteredWindow({url, width, height}) {
    const pos = {
        x: (screen.width / 2) - (width / 2),
        y: (screen.height/2) - (height / 2)
    };

    const features = `width=${width} height=${height} left=${pos.x} top=${pos.y}`;

    return window.open(url, '_blank', features);
}

Thí dụ

openCenteredWindow({
    url: 'https://stackoverflow.com/', 
    width: 500, 
    height: 600
}).focus();

2

(điều này đã được đăng vào năm 2020)

Một phần mở rộng cho câu trả lời của CrazyTim

Bạn cũng có thể đặt chiều rộng thành tỷ lệ phần trăm (hoặc tỷ lệ) cho kích thước động. Kích thước tuyệt đối vẫn được chấp nhận.

function popupWindow(url, title, w='75%', h='16:9', opts){
    // sort options
    let options = [];
    if(typeof opts === 'object'){
        Object.keys(opts).forEach(function(value, key){
            if(value === true){value = 'yes';}else if(value === false){value = 'no';}
            options.push(`${key}=${value}`);
        });
        if(options.length){options = ','+options.join(',');}
        else{options = '';}
    }else if(Array.isArray(opts)){
        options = ','+opts.join(',');
    }else if(typeof opts === 'string'){
        options = ','+opts;
    }else{options = '';}

    // add most vars to local object (to shorten names)
    let size = {w: w, h: h};
    let win = {w: {i: window.top.innerWidth, o: window.top.outerWidth}, h: {i: window.top.innerHeight, o: window.top.outerHeight}, x: window.top.screenX || window.top.screenLeft, y: window.top.screenY || window.top.screenTop}

    // set window size if percent
    if(typeof size.w === 'string' && size.w.endsWith('%')){size.w = Number(size.w.replace(/%$/, ''))*win.w.o/100;}
    if(typeof size.h === 'string' && size.h.endsWith('%')){size.h = Number(size.h.replace(/%$/, ''))*win.h.o/100;}

    // set window size if ratio
    if(typeof size.w === 'string' && size.w.includes(':')){
        size.w = size.w.split(':', 2);
        if(win.w.o < win.h.o){
            // if height is bigger than width, reverse ratio
            size.w = Number(size.h)*Number(size.w[1])/Number(size.w[0]);
        }else{size.w = Number(size.h)*Number(size.w[0])/Number(size.w[1]);}
    }
    if(typeof size.h === 'string' && size.h.includes(':')){
        size.h = size.h.split(':', 2);
        if(win.w.o < win.h.o){
            // if height is bigger than width, reverse ratio
            size.h = Number(size.w)*Number(size.h[0])/Number(size.h[1]);
        }else{size.h = Number(size.w)*Number(size.h[1])/Number(size.h[0]);}
    }

    // force window size to type number
    if(typeof size.w === 'string'){size.w = Number(size.w);}
    if(typeof size.h === 'string'){size.h = Number(size.h);}

    // keep popup window within padding of window size
    if(size.w > win.w.i-50){size.w = win.w.i-50;}
    if(size.h > win.h.i-50){size.h = win.h.i-50;}

    // do math
    const x = win.w.o / 2 + win.x - (size.w / 2);
    const y = win.h.o / 2 + win.y - (size.h / 2);
    return window.open(url, title, `width=${size.w},height=${size.h},left=${x},top=${y}${options}`);
}

sử dụng:

// width and height are optional (defaults: width = '75%' height = '16:9')
popupWindow('https://www.google.com', 'Title', '75%', '16:9', {/* options (optional) */});

// options can be an object, array, or string

// example: object (only in object, true/false get replaced with 'yes'/'no')
const options = {scrollbars: false, resizable: true};

// example: array
const options = ['scrollbars=no', 'resizable=yes'];

// example: string (same as window.open() string)
const options = 'scrollbars=no,resizable=yes';

1
function fnPopUpWindow(pageId) {
     popupwindow("hellowWorld.php?id="+pageId, "printViewer", "500", "300");
}

function popupwindow(url, title, w, h) {
    var left = Math.round((screen.width/2)-(w/2));
    var top = Math.round((screen.height/2)-(h/2));
    return window.open(url, title, 'toolbar=no, location=no, directories=no, status=no, '
            + 'menubar=no, scrollbars=yes, resizable=no, copyhistory=no, width=' + w 
            + ', height=' + h + ', top=' + top + ', left=' + left);
}
<a href="javascript:void(0);" onclick="fnPopUpWindow('10');">Print Me</a>

Lưu ý: bạn phải sử dụng Math.roundđể lấy số nguyên chính xác của chiều rộng và chiều cao.


0

Dựa trên Facebook nhưng sử dụng truy vấn phương tiện thay vì regex tác nhân người dùng để calc nếu có đủ chỗ (có một số không gian) cho cửa sổ bật lên, nếu không thì toàn màn hình. Tbh bật lên trên điện thoại di động mở dưới dạng các tab mới.

function popupCenter(url, title, w, h) {
  const hasSpace = window.matchMedia(`(min-width: ${w + 20}px) and (min-height: ${h + 20}px)`).matches;
  const isDef = v => typeof v !== 'undefined';
  const screenX = isDef(window.screenX) ? window.screenX : window.screenLeft;
  const screenY = isDef(window.screenY) ? window.screenY : window.screenTop;
  const outerWidth = isDef(window.outerWidth) ? window.outerWidth : document.documentElement.clientWidth;
  const outerHeight = isDef(window.outerHeight) ? window.outerHeight : document.documentElement.clientHeight - 22;
  const targetWidth = hasSpace ? w : null;
  const targetHeight = hasSpace ? h : null;
  const V = screenX < 0 ? window.screen.width + screenX : screenX;
  const left = parseInt(V + (outerWidth - targetWidth) / 2, 10);
  const right = parseInt(screenY + (outerHeight - targetHeight) / 2.5, 10);
  const features = [];

  if (targetWidth !== null) {
    features.push(`width=${targetWidth}`);
  }

  if (targetHeight !== null) {
    features.push(`height=${targetHeight}`);
  }

  features.push(`left=${left}`);
  features.push(`top=${right}`);
  features.push('scrollbars=1');

  const newWindow = window.open(url, title, features.join(','));

  if (window.focus) {
    newWindow.focus();
  }

  return newWindow;
}

0

Giải pháp lai này hoạt động với tôi, cả trên thiết lập màn hình đơn và kép

function popupCenter (url, title, w, h) {
    // Fixes dual-screen position                              Most browsers      Firefox
    const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : window.screenX;
    const dualScreenTop = window.screenTop !== undefined ? window.screenTop : window.screenY;
    const left = (window.screen.width/2)-(w/2) + dualScreenLeft;
    const top = (window.screen.height/2)-(h/2) + dualScreenTop;
    return window.open(url, title, 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width='+w+', height='+h+', top='+top+', left='+left);
}

0

Tôi gặp vấn đề với việc định tâm cửa sổ bật lên trong màn hình ngoài và window.screenXwindow.screenY tương ứng là các giá trị âm (-1920, -1200). Tôi đã thử tất cả các giải pháp được đề xuất ở trên và chúng hoạt động tốt trong các màn hình chính. Tôi muốn rời đi

  • Lề 200 px cho trái và phải
  • Biên độ 150 px cho đỉnh và đáy

Đây là những gì làm việc cho tôi:

 function createPopupWindow(url) {
    var height = screen.height;
    var width = screen.width;
    var left, top, win;

    if (width > 1050) {
        width = width - 200;
    } else {
        width = 850;
    }

    if (height > 850) {
        height = height - 150;
    } else {
        height = 700;
    }

    if (window.screenX < 0) {
        left = (window.screenX - width) / 2;
    } else {
        left = (screen.width - width) / 2;
    }

    if (window.screenY < 0) {
        top = (window.screenY + height) / 4;
    } else {
        top = (screen.height - height) / 4;
    }

    win=window.open( url,"myTarget", "width="+width+", height="+height+",left="+left+",top="+top+"menubar=no, status=no, location=no, resizable=yes, scrollbars=yes");
    if (win.focus) {
        win.focus();
    }
}

-4

.center{
    left: 50%;
    max-width: 350px;
    padding: 15px;
    text-align:center;
    position: relative;
    transform: translateX(-50%);
    -moz-transform: translateX(-50%);
    -webkit-transform: translateX(-50%);
    -ms-transform: translateX(-50%);
    -o-transform: translateX(-50%);   
}

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.